2009-12-17 63 views
28

我試圖得到Django URL namespaces的掛起。但我找不到任何示例或文檔。你如何使用Django URL命名空間?

這是我試過的。

urls.py:

from django.conf.urls.defaults import * 

urlpatterns = patterns('', 
    (r'^foo/', include('sub_urls', namespace='foo', app_name='foo')), 
    (r'^bar/', include('sub_urls', namespace='bar', app_name='bar')),    
) 

sub_urls.py:

from django.conf.urls.defaults import patterns, url 
from views import view1 

urlpatterns = patterns('views', 
    url(r'^(?P<view_id>\d+)/$', view1, name='view1') 
) 

views.py:

from django.shortcuts import render_to_response 

def view1(request, view_id): 
    return render_to_response('view1.html', locals()) 

在view1.html,{%URL FOO:廠景3% } outputs/foo/3和{%url bar:view1 3%} outputs/bar/3。無論我瀏覽到/ foo/X還是/ bar/X,情況都是如此。

我想要的是能夠瀏覽到/ foo/X或/ bar/X,並且{%url view1 3%}分別輸出/ foo/3或/ bar/3。

+0

我這樣做的原因是,我可以讓這兩個名稱空間使用不同的CSS文件。即在/ foo下瀏覽會包含foo.css,而/ bar會包含bar.css。 – 2009-12-17 03:47:57

+0

我會意識到,擁有相同內容的不同網址一定會讓您的網站在搜索引擎上受到懲罰。我不知道這是否是您的擔憂,但如果是這樣,我會建議以其他方式來解決這個問題。也許你可以在客戶端設置一個cookie,並讓他們以其他方式選擇CSS樣式。 – Clueless 2010-01-21 01:53:08

+0

我最終根據不同的子域來設置CSS。本地測試只是一個痛苦,需要hostfile條目。 – 2010-01-22 14:24:48

回答

3

我認爲這在django中是不可能的。看看這message board post其中引用Ticket 11559。我認爲你正在嘗試做同樣的事情 - 有效地將一個隱式參數傳遞給URL標記。

此外,假設sub_urls是來自同一個應用程序的兩次,您應該確保app_name在兩種情況下都是相同的。你只需要改變命名空間。

0

這是我想出的一個解決方案。

views.py:

from django.shortcuts import render_to_response 
from django.template import RequestContext 

def render_response_context(view, locals): 
    request = locals["request"] 
    app = "bar" if request.META["PATH_INFO"].lower().startswith("/bar") else "foo" 
    return render_to_response(view, locals, 
     context_instance=RequestContext(request, current_app=app)) 

def view1(request, view_id):  
    return render_response_context('view1.html', locals()) 

view1.html:

{% load extras %} 
{% namespace_url view1 3 %} 

extras.py:

from django import template 
from django.core.urlresolvers import reverse 

register = template.Library() 

@register.tag 
def namespace_url(parser, token): 
    tag_name, view_string, arg1 = token.split_contents() 
    return NamespaceUrlNode(view_string, arg1) 

class NamespaceUrlNode(template.Node): 
    def __init__(self, view_string, arg1): 
     self.view_string = view_string 
     self.arg1 = arg1 
    def render(self, context): 
     return reverse("%s:%s" % (context.current_app, self.view_string), args=[self.arg1]) 

基本上我確信總是通過CURRENT_APP上下文或者「 foo「或」bar「,我通過查看請求URL手動計算。然後我使用自定義標籤來解析基於current_app的URL。

這不是非常通用的; 「foo」和「bar」是硬編碼的,標籤只能使用一個參數。即使解決了這些問題,這似乎也是一種破解。

0

我知道下面的解決方案違反DRY主體,因爲您必須爲foo和bar創建基本上重複的url配置文件,但我認爲它應該可以工作。

urls.py:

from django.conf.urls.defaults import * 

urlpatterns = patterns('', 
    (r'^foo/', include('sub_urls_foo')), 
    (r'^bar/', include('sub_urls_bar')),    
) 

sub_urls_foo.py:

from django.conf.urls.defaults import patterns, url 
from views import view1 

urlpatterns = patterns('views', 
    url(r'^(?P<view_id>\d+)/$', view1, 'view1_foo', {'namespace': 'view1_foo'}) 
) 

sub_urls_bar.py:

from django.conf.urls.defaults import patterns, url 
from views import view1 

urlpatterns = patterns('views', 
    url(r'^(?P<view_id>\d+)/$', view1, 'view1_bar', {'namespace': 'view1_bar'}) 
) 

views.py:

from django.shortcuts import render_to_response 

def view1(request, view_id, namespace): 
    return render_to_response('view1.html', locals()) 

然後在模板中使用這樣的:

{% url namespace 3 %} 

我沒有測試在{%URL%}標籤的名稱部分使用變量的想法,但我認爲它應該工作。

+0

所以你需要使用{%url view1_bar 3%}或{%url view1_foo 3%}?我真正想要的是能夠使用{%url view1 3%},並根據哪個名稱空間匹配當前URL來選擇foo或bar。 – 2010-01-22 14:21:14

+0

您的權利,我的示例不起作用。我假設我可以將一個模板變量傳遞給{%url%}標籤。我現在讀的不是這種情況。這給你留下了兩個選擇。要麼使用reverse()處理視圖中的url,並將其在上下文中傳遞給模板,或者創建自定義模板標記。 – 2010-01-23 05:52:52

5

似乎沒有直接的方法來做到這一點。我會使用一個類似的解決方案,就像您使用模板標籤介紹的那樣,但我找到了更通用的方法。我用的是事實,你可以在你的URL的conf傳遞可選參數,這樣你就可以跟蹤命名空間:

#urls.py 
from django.conf.urls import defaults 

urlpatterns = defaults.patterns('', 
    defaults.url(r'^foo/', include('sub_urls', namespace='foo', app_name='myapp'), 
    kwargs={'namespace':'foo'}), 
    defaults.url(r'^bar/', include('sub_urls', namespace='bar', app_name='myapp'), 
    kwargs={'namespace':'bar'}),  
) 

這也違背了DRY原則,但並不多,雖然:)

然後在你的觀點,你得到的命名空間的變量(sub_urls.py將是相同的):

#views.py 
from django import shortcuts 

def myvew(request, namespace): 
    context = dict(namespace=namespace) 
    return shortcuts.render_to_response('mytemplate.html', context) 

後來你只需要一個簡單的標籤你通過命名空間的變量和視圖名稱:

#tags.py 
from django import template 
from django.core import urlresolvers 

register = template.Library() 

def namespace_url(namespace, view_name): 
    return urlresolvers.reverse('%s:%s' % (namespace, view_name, args=args, kwargs=kwargs))) 
register.simple_tag(namespace_url) 

,並在模板中使用它(請務必通過您的視圖的名字作爲一個字符串,而不是作爲一個模板變量):

<!-- mytemplate.html --> 
{% load tags %} 
{% namespace_url namespace "view1"%} 

感謝您的提示順便說一句..我一直在尋找某物。喜歡這個。

+0

我看到這是一篇很老的文章,但是,dict(namespace = namespace)在計算上比{'namespace':namespace}更昂貴。用'dis'找出原因! – explodes 2012-12-20 21:24:22

+0

對namespace_url函數的小改動: def namespace_url(namespace,view_name,* args,** kwargs): return urlresolvers.reverse('%s:%s'%(namespace,view_name),args = args,kwargs = kwargs) 將允許您支持url參數 – georgerw 2014-07-11 23:16:26

+0

Thx。很好的補充。將它添加到答案中。 – 2014-07-14 09:33:12