2009-12-17 19 views
28

Sto cercando di ottenere il blocco di Django URL namespaces. Ma non riesco a trovare alcun esempio o documentazione.Come si usano gli spazi dei nomi URL di Django?

Ecco cosa ho provato.

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()) 

In view1.html, {url% pippo: view1 3% } output/foo/3 e {% url bar: view1 3%} output/bar/3. Ciò è vero sia che navighi in/foo/X o/bar/X.

Quello che voglio è essere in grado di navigare in/foo/X o/bar/X e avere {% url view1 3%} output rispettivamente/foo/3 o/bar/3, rispettivamente.

+0

La ragione per cui sto facendo questo è che posso far sì che i due spazi dei nomi utilizzino diversi file CSS. Cioè la navigazione sotto/foo includerebbe foo.css e/bar includerebbe bar.css. –

+0

Sarei consapevole che avere URL diversi con lo stesso contenuto renderà sicuramente il tuo sito penalizzato sui motori di ricerca. Non so se questo sia un problema per te o no, ma se lo fosse, ti consiglierei di aggirare questo aspetto in un altro modo. Forse potresti impostare un cookie sul client e fargli scegliere gli stili CSS in un altro modo. – Clueless

+0

Ho finito per impostare il CSS in base a diversi sottodomini. È solo un problema da testare localmente, che richiede le voci del file host. –

risposta

3

Penso che questo non sia possibile in Django in questo momento. Date un'occhiata a questo message board post che fa riferimento a Ticket 11559.Penso che tu stia cercando di fare la stessa cosa: passare in effetti un parametro implicito al tag URL.

Inoltre, supponendo che sub_urls provenga dalla stessa app entrambe le volte è necessario assicurarsi che lo app_name sia lo stesso in entrambi i casi. Dovresti solo cambiare spazio dei nomi.

0

Ecco una soluzione che ho trovato.

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]) 

Fondamentalmente ho fatto in modo di passare sempre il contesto CURRENT_APP come " foo "o" bar ", che calcolo manualmente osservando l'URL della richiesta. Quindi uso un tag personalizzato che risolve un URL basato su current_app.

Non è molto generico; "foo" e "bar" sono hard-coded e il tag può richiedere solo un argomento. Anche con questi problemi risolti, questo sembra un trucco.

0

Mi rendo conto che la soluzione sottostante viola il principale di DRY poiché è necessario creare file di configurazione URL essenzialmente duplicati per foo e bar, tuttavia penso che dovrebbe funzionare.

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()) 
.210

E poi per il modello utilizzare questo:

{% url namespace 3 %} 

non ho ancora testato l'idea di utilizzare una variabile nella sezione nome del tag {% url%}, ma penso che dovrebbe funzionare.

+0

Quindi dovresti utilizzare {% url view1_bar 3%} o {% url view1_foo 3%}? Quello che voglio davvero è poter usare {% url view1 3%}, e farlo scegliere foo o bar a seconda di quale spazio dei nomi corrisponde all'URL corrente. –

+0

Vostro diritto, il mio esempio non funzionerà. L'ho costruito supponendo di poter passare una variabile modello al tag {% url%}. Che ora ho letto non è il caso. Quindi questo ti lascia due opzioni. Elabora l'url nella tua vista usando reverse() e passa nel contesto al modello, oppure crea un tag modello personalizzato. –

5

Non sembra esserci un modo diretto per farlo. Vorrei usare una soluzione simile come hai introdotto usando un tag modello, anche se ho trovato un modo più generico. Ho usato il fatto che è possibile passare parametri opzionali nella tua conf URL, in modo da poter tenere traccia dello spazio dei nomi:

#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'}),  
) 

che viola anche il principio DRY, ma non molto però :)

Poi, nel la visualizzazione si ottiene la variabile namespace (sub_urls.py sarebbe lo stesso):

#views.py 
from django import shortcuts 

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

in seguito è sufficiente un semplice tag si passa la variabile dello spazio dei nomi e il nome al fine di:

#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) 

e utilizzarlo nel modello (assicurarsi di passare il vostro nome della vista come una stringa, e non come una variabile di modello):

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

Grazie per il suggerimento btw .. Ero alla ricerca di qc. come questo.

+0

Vedo che questo è un post molto vecchio, tuttavia, dict (namespace = namespace) è computazionalmente più costoso di {'namespace': namespace}. Usa 'dis' per scoprire perché! – explodes

+0

piccolo cambiamento alla funzione namespace_url: def namespace_url (namespace, nome_vista, * args, ** kwargs): ritorno urlresolvers.reverse ('% s:% s' % (namespace, nome_vista), args = args, kwargs = kwargs) Vi consentirà di supportare i parametri url – georgerw

+0

Thx. Bella aggiunta Aggiunto alla risposta. –

Problemi correlati