web-dev-qa-db-fra.com

Un véritable exemple d'espace de noms d'URL

J'étudie la documentation Django, mais j'ai rencontré une partie que je ne peux pas comprendre: quel est un exemple réel de la façon d'utiliser un espace de noms dans un vrai problème. Je connais la syntaxe mais je le fais sais pas le but de cela.

30
Harold Finch

En règle générale, ils sont utilisés pour placer les URL de chaque application dans leur propre espace de noms. Cela empêche la fonction reverse() Django et la fonction de modèle {% url %} De renvoyer la mauvaise URL car le nom du modèle d'URL correspondait dans une autre application.

Ce que j'ai dans mon fichier urls.py Au niveau du projet est le suivant:

from Django.conf.urls.defaults import *
from Django.conf import settings
from Django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$', 'main.views.main', name='main'),
    url(r'^login$', 'Django.contrib.auth.views.login', name="login"),
    url(r'^logout$', 'Django.contrib.auth.views.logout',
        {"next_page": "/"}, name="logout"),

# Admin
    url(r'^admin/doc/', include('Django.contrib.admindocs.urls')),
    url(r'^admin/', include(admin.site.urls)),
)

# Auto-add the applications.
for app in settings.LOCAL_APPS:
    urlpatterns += patterns('',
        url(r'^{0}/'.format(app), include(app + '.urls', namespace=app)),
    )

Notez la dernière section: cela passe par les applications que j'ai installées (settings.LOCAL_APPS Est un paramètre que j'ai ajouté qui ne contient que mes applications; il est ajouté à INSTALLED_APPS Qui a d'autres choses comme South), ressemble pour un urls.py dans chacun d'eux, et importe ces URL dans un espace de noms nommé d'après l'application, et place également ces URL dans un sous-répertoire d'URL nommé d'après l'application.

Ainsi, par exemple, si j'ai une application nommée hosts et que hosts/urls.py Ressemble à:

from Django.conf.urls.defaults import *

urlpatterns = patterns('hosts.views',
    url(r'^$', 'show_hosts', name='list'),
)

Maintenant, mon views.py Peut appeler reverse("hosts:list") pour obtenir l'URL de la page qui appelle hosts.views.show_hosts, Et cela ressemblera à "/hosts/". Il en va de même pour {% url "hosts:list" %} Dans un modèle. De cette façon, je n'ai pas à me soucier d'entrer en collision avec une URL nommée "liste" dans une autre application, et je n'ai pas à préfixer chaque nom avec hosts_.

Notez que la page de connexion est à {% url "login" %} Car aucun espace de noms ne lui a été attribué.

35
Mike DeSimone

Considérez que vous utilisez un modèle d'URL comme ci-dessous
url(r'^login/',include('app_name', name='login'))

Considérez également que vous utilisez une application tierce comme Django-RestFramework. Lorsque vous utilisez l'application, vous devez déclarer la ligne suivante dans le fichier conf des URL du projet.

url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))

Maintenant, si vous vérifiez le code de rest-framework, vous trouverez le code ci-dessous dans le fichier urls.py

urlpatterns = [
    url(r'^login/$', login, login_kwargs, name='login'),
    url(r'^logout/$', logout, name='logout'),
]

Nous avons utilisé le nom de connexion pour un modèle d'URL dans notre projet et le même nom est utilisé par Django-rest-framework pour l'un de leurs modèles d'URL. Lorsque vous utilisez reverse ('login'), Django sera confus.
Pour résoudre ces types de problèmes, nous utilisons l'espace de noms.

@register.simple_tag
def optional_docs_login(request):
    """
    Include a login snippet if REST framework's login view is in the URLconf.
    """
    try:
        login_url = reverse('rest_framework:login')
    except NoReverseMatch:
        return 'log in'

Les noms d'URL d'un espace de noms n'entreront jamais en collision avec d'autres espaces de noms.
Un modèle d'URL avec espace de noms peut être inversé à l'aide de
reverse('namespace:url_name')

5
nikhil ponnuru

Nous utilisons également l'espace de noms dans le middleware pour gérer certains différemment

    def process_response(self, request, response):
        try:
            if resolve(request.path).namespace == 'special_namespace':
                response['Custom-Header'] = 'Custom-Value'
            return response
        except Resolver404:
            return response
0
darkrat