J'essaie de comprendre les espaces de noms d'URL Django . Mais je ne trouve aucun exemple ou documentation.
Voici ce que j'ai essayé.
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())
Dans view1.html, {% url foo: view1 3%} sorties/foo/3 et {% url bar: view1 3%} sorties/bar/3. Cela est vrai que je navigue vers/foo/X ou/bar/X.
Ce que je veux, c'est pouvoir accéder à/foo/X ou/bar/X, et avoir {% url view1 3%} le résultat final soit/foo/3 ou/bar/3, respectivement.
Je pense que ce n'est pas possible à Django pour le moment. Jetez un coup d’œil à/ Message du forum qui fait référence Ticket 11559 . Je pense que vous essayez de faire la même chose: transmettre efficacement un paramètre implicite à la balise URL.
En outre, en supposant que sub_urls
provient de la même application les deux fois, vous devez vous assurer que app_name
est identique dans les deux cas. Vous ne devriez avoir besoin que de changer d'espace de nom.
Il semble n'y avoir aucun moyen direct de le faire. Je voudrais utiliser une solution similaire à celle que vous avez introduite en utilisant une balise de modèle, bien que j'ai trouvé une manière plus générique. J'ai utilisé le fait que vous pouvez passer des paramètres optionnels dans votre conf url, afin que vous puissiez garder une trace de l'espace de noms:
#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'}),
)
Cela viole également le principe DRY, mais pas beaucoup :)
Ensuite, dans votre vue, vous obtenez la variable d'espace de nom (sub_urls.py serait identique):
#views.py
from Django import shortcuts
def myvew(request, namespace):
context = dict(namespace=namespace)
return shortcuts.render_to_response('mytemplate.html', context)
Plus tard, vous avez juste besoin d’une simple balise à laquelle vous transmettez votre variable d’espace de nom et votre nom de vue:
#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)
et utilisez-le dans le modèle (assurez-vous de transmettre votre nom de vue en tant que chaîne et non en tant que variable de modèle):
<!-- mytemplate.html -->
{% load tags %}
{% namespace_url namespace "view1"%}
Merci pour votre suggestion, btw .. Je cherchais qc. comme ça.
Voici une solution que je suis venu avec.
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])
En gros, je me suis assuré de toujours passer le contexte current_app sous la forme "foo" ou "bar", que je calcule manuellement en regardant l'URL de la requête. Ensuite, j'utilise une balise personnalisée qui résout une URL basée sur current_app.
Ce n'est pas très générique; "foo" et "bar" sont codés en dur, et la balise ne peut prendre qu'un seul argument. Même avec ces problèmes résolus, cela semble être un hack.
Je me rends compte que la solution ci-dessous viole le principe DRY, car vous devez créer essentiellement des fichiers de configuration d'URL en double pour foo et bar, mais je pense que cela devrait fonctionner.
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())
Et puis, pour le modèle, utilisez ceci:
{% url namespace 3 %}
Je n'ai pas testé l'idée d'utiliser une variable dans la section name de la balise {% url%}, mais je pense que cela devrait fonctionner.