Distribution des URL

Une organisation propre et élégante des URL est un aspect important dans une application Web de qualité. Django vous laisse organiser vos URL comme bon vous semble, sans restriction imposée par le système.

Pas besoin de .php ou de .cgi, et encore moins de 0,2097,1-1-1928,00.

Lisez Cool URIs don’t change, par le père du World Wide Web Tim Berners-Lee, pour savoir pourquoi les URL devraient être claires et conviviales.

Aperçu

To design URLs for an app, you create a Python module informally called a URLconf (URL configuration). This module is pure Python code and is a mapping between URL path expressions to Python functions (your views).

Cette correspondance peut être autant courte que longue. Elle peut faire référence à d’autres correspondances. Et étant donné qu’il s’agit de code Python pur, elle peut être construite dynamiquement.

Django fournit également une façon de traduire les URL en fonction de la langue active. Voir la documentation sur l’internationalisation pour plus d’informations.

Processus de traitement des requêtes par Django

Quand un utilisateur accède à une page de votre site Django, voici l’algorithme que le système suit pour déterminer quel code Python doit être exécuté :

  1. Django identifie le module URLconf racine à utiliser. Par défaut, c’est la valeur attribuée au réglage ROOT_URLCONF, mais si la requête HttpRequest entrante possède un attribut urlconf (défini par intergiciel), sa valeur sera utilisée en lieu et place du réglage ROOT_URLCONF.
  2. Django loads that Python module and looks for the variable urlpatterns. This should be a Python list of django.urls.path() and/or django.urls.re_path() instances.
  3. Django parcourt chaque motif d’URL dans l’ordre et s’arrête dès la première correspondance avec l’URL demandée.
  4. Once one of the URL patterns matches, Django imports and calls the given view, which is a simple Python function (or a class-based view). The view gets passed the following arguments:
    • Une instance HttpRequest.
    • If the matched URL pattern returned no named groups, then the matches from the regular expression are provided as positional arguments.
    • The keyword arguments are made up of any named parts matched by the path expression, overridden by any arguments specified in the optional kwargs argument to django.urls.path() or django.urls.re_path().
  5. If no URL pattern matches, or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view. See Error handling below.

Exemple

Voici un exemple d’URLconf :

from django.urls import path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]

Notes :

  • To capture a value from the URL, use angle brackets.
  • Captured values can optionally include a converter type. For example, use <int:name> to capture an integer parameter. If a converter isn’t included, any string, excluding a / character, is matched.
  • There’s no need to add a leading slash, because every URL has that. For example, it’s articles, not /articles.

Exemples de requêtes :

  • A request to /articles/2005/03/ would match the third entry in the list. Django would call the function views.month_archive(request, year=2005, month=3).
  • /articles/2003/ correspondrait au premier motif de la liste, et non le deuxième, car les motifs sont évalués dans l’ordre, et le premier est le premier à correspondre. Libre à vous d’utiliser l’ordre de définition pour traiter des cas spéciaux comme ici. Ici, Django appellerait la fonction views.special_case_2003(request).
  • /articles/2003 ne correspondrait à aucun motif, car chaque motif nécessite que l’URL se termine par une barre oblique.
  • /articles/2003/03/building-a-django-site/ would match the final pattern. Django would call the function views.article_detail(request, year=2003, month=3, slug="building-a-django-site").

Path converters

The following path converters are available by default:

  • str - Matches any non-empty string, excluding the path separator, '/'. This is the default if a converter isn’t included in the expression.
  • int - Matches zero or any positive integer. Returns an int.
  • slug - Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters. For example, building-your-1st-django-site.
  • uuid - Matches a formatted UUID (letters must be lowercase). For example, 075194d3-6885-417e-a8a8-6c931e272f00. Returns a UUID instance.
  • path - Matches any non-empty string, including the path separator, '/'. This allows you to match against a complete URL path rather than just a segment of a URL path as with str.

Registering custom path converters

For more complex matching requirements, you can define your own path converters.

A converter is a class that includes the following:

  • A regex class attribute, as a string.
  • A to_python(self, value) method, which handles converting the matched string into the type that should be passed to the view function. It should raise ValueError if it can’t convert the given value.
  • A to_url(self, value) method, which handles converting the Python type into a string to be used in the URL.

Par exemple :

class FourDigitYearConverter:
    regex = '[0-9]{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return '%04d' % value

Register custom converter classes in your URLconf using register_converter():

from django.urls import register_converter, path

from . import converters, views

register_converter(converters.FourDigitYearConverter, 'yyyy')

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<yyyy:year>/', views.year_archive),
    ...
]

Using regular expressions

If the paths and converters syntax isn’t sufficient for defining your URL patterns, you can also use regular expressions. To do so, use re_path() instead of path().

In Python regular expressions, the syntax for named regular expression groups is (?P<name>pattern), where name is the name of the group and pattern is some pattern to match.

Here’s the example URLconf from earlier, rewritten using regular expressions:

from django.urls import path, re_path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    re_path('articles/(?P<year>[0-9]{4})/', views.year_archive),
    re_path('articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/', views.month_archive),
    re_path('articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-_]+)/', views.article_detail),
]

This accomplishes roughly the same thing as the previous example, except:

  • The exact URLs that will match are slightly more constrained. For example, the year 10000 will no longer match since the year integers are constrained to be exactly four digits long.
  • Each captured argument is sent to the view as a string, regardless of what sort of match the regular expression makes.

When switching from using path() to re_path() or vice versa, it’s particularly important to be aware that the type of the view arguments may change, and so you may need to adapt your views.

Using unnamed regular expression groups

As well as the named group syntax, e.g. (?P<year>[0-9]{4}), you can also use the shorter unnamed group, e.g. ([0-9]{4}).

This usage isn’t particularly recommended as it makes it easier to accidentally introduce errors between the intended meaning of a match and the arguments of the view.

In either case, using only one style within a given regex is recommended. When both styles are mixed, any unnamed groups are ignored and only named groups are passed to the view function.

Paramètres imbriqués

Les expressions régulières autorisent les paramètres imbriqués et Django les résout et les transmet à la vue. Lors de l’inversion d’URL, Django essaie de remplir tous les paramètres capturés externes, en ignorant les paramètres capturés imbriqués. Considérez les motifs d’URL suivants qui acceptent de manière facultative un paramètre page:

from django.urls import re_path

urlpatterns = [
    re_path(r'blog/(page-(\d+)/)?$', blog_articles),                  # bad
    re_path(r'comments/(?:page-(?P<page_number>\d+)/)?$', comments),  # good
]

Les deux motifs emploient des paramètres imbriqués et seront résolus : par exemple, blog/page-2/ va correspondre à blog_articles avec deux paramètres positionnels : page-2/ et 2. Le second motif pour comments va correspondre à comments/page-2/ avec le paramètre nommé page_number défini à 2. Le paramètre extérieur dans ce cas est un paramètre non capturant (?:...).

La vue blog_articles a besoin du paramètre capturé extérieur afin d’être résolue, page-2/ ou aucun paramètre, dans ce cas, alors que comments peut être résolue avec soit aucun paramètre, soit une valeur pour page_number.

Les paramètres capturés imbriqués créent un couplage fort entre les paramètres de la vue et l’URL, comme le démontre blog_articles: la vue reçoit une partie de l’URL (page-2/) au lieu de ne recevoir que la valeur qui l’intéresse réellement. Ce couplage est encore plus prononcé lors de la résolution, car pour résoudre la vue, il est nécessaire de transmettre un bout d’URL au lieu d’un simple numéro de page.

En règle générale, capturez uniquement les valeurs que la vue doit gérer et employez des paramètres sans capture lorsque l’expression régulière a besoin d’un paramètre mais que la vue l’ignore.

Configurations d’URL et contenu des comparaisons

L”URLconf utilise l’URL demandée, en tant que simple chaîne Python. Ni les paramètres GET ou POST, ni le nom de domaine ne sont inclus.

Par exemple, pour une requête sur https://www.example.com/myapp/, l”URLconf cherchera myapp/.

Pour une requête sur https://www.example.com/myapp/?page=3, l”URLconf cherchera myapp/.

L”URLconf ignore la méthode de la requête. En d’autres termes, toutes les méthodes de requêtes – POST, GET, HEAD, etc. – seront acheminées vers la même fonction de la même URL.

Valeurs par défaut des paramètres de vue

Une astuce pratique est de définir des valeurs par défaut pour les paramètres de vos vues. Voici un exemple de configuration d’URL et de vue :

# URLconf
from django.urls import path

from . import views

urlpatterns = [
    path('blog/', views.page),
    path('blog/page<int:num>/', views.page),
]

# View (in blog/views.py)
def page(request, num=1):
    # Output the appropriate page of blog entries, according to num.
    ...

In the above example, both URL patterns point to the same view – views.page – but the first pattern doesn’t capture anything from the URL. If the first pattern matches, the page() function will use its default argument for num, 1. If the second pattern matches, page() will use whatever num value was captured.

Performance

Chaque expression régulière d’un urlpatterns est compilée la première fois qu’elle est utilisée. Cela rend le système extrêmement rapide.

Syntaxe de la variable urlpatterns

urlpatterns should be a Python list of path() and/or re_path() instances.

Gestion d’erreur

When Django can’t find a match for the requested URL, or when an exception is raised, Django invokes an error-handling view.

Les vues à utiliser pour ces situations sont définies par quatre variables. Leur valeur par défaut devraient convenir à la plupart des projets, mais il reste possible de les personnaliser en surchargeant leurs valeurs par défaut.

Voir la documentation sur la personnalisation des vues d’erreur pour plus de détails.

Ces valeurs doivent être définies dans l”URLconf racine. La définition de ces variables dans n’importe quel autre URLconf n’aura aucun effet.

Les valeurs doivent pouvoir être appelées, ou être des chaînes de caractères représentant le chemin d’importation Python complet vers une vue qui doit être appelée pour traiter l’erreur actuelle.

Les variables sont :

Inclusion d’autres URLconfs

À tout moment, votre urlpatterns peut « inclure » d’autres modules URLconf. Fondamentalement, cela permet de rassembler un ensemble d’URL les unes sous les autres.

Par exemple, voici un extrait de la configuration d’URL du site Web Django lui-même. Il inclut un certain nombre d’autres configurations d’URL :

from django.urls import include, path

urlpatterns = [
    # ... snip ...
    path('community/', include('aggregator.urls')),
    path('contact/', include('contact.urls')),
    # ... snip ...
]

Whenever Django encounters include(), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.

Another possibility is to include additional URL patterns by using a list of path() instances. For example, consider this URLconf:

from django.urls import include, path

from apps.main import views as main_views
from credit import views as credit_views

extra_patterns = [
    path('reports/', credit_views.report),
    path('reports/<int:id>/', credit_views.report),
    path('charge/', credit_views.charge),
]

urlpatterns = [
    path('', main_views.homepage),
    path('help/', include('apps.help.urls')),
    path('credit/', include(extra_patterns)),
]

Dans cet exemple, l’URL /credit/reports/ sera traitée par la vue Django credit_views.report().

Cela peut être utilisé pour supprimer de la redondance dans des configurations d’URL où un préfixe de motif est employé de manière répétitive. Par exemple, considérez cette configuration d’URL :

from django.urls import path
from . import views

urlpatterns = [
    path('<page_slug>-<page_id>/history/', views.history),
    path('<page_slug>-<page_id>/edit/', views.edit),
    path('<page_slug>-<page_id>/discuss/', views.discuss),
    path('<page_slug>-<page_id>/permissions/', views.permissions),
]

Nous pouvons l’améliorer en indiquant une seule fois le préfixe de chemin commun et en regroupant les suffixes qui diffèrent :

from django.urls import include, path
from . import views

urlpatterns = [
    path('<page_slug>-<page_id>/', include([
        path('history/', views.history),
        path('edit/', views.edit),
        path('discuss/', views.discuss),
        path('permissions/', views.permissions),
    ])),
]

Les paramètres capturés

Un URLconf inclus reçoit tous les paramètres capturés par ses URLconf parents, ainsi l’exemple suivant est valide :

# In settings/urls/main.py
from django.urls import include, path

urlpatterns = [
    path('<username>/blog/', include('foo.urls.blog')),
]

# In foo/urls/blog.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.blog.index),
    path('archive/', views.blog.archive),
]

Dans l’exemple ci-dessus, la variable capturée "username" est passée à l”URLconf inclus, comme on peut s’y attendre.

Transmission de paramètres supplémentaires à une vue

Les configurations d’URL ont un point d’entrée qui permet de passer des paramètres supplémentaires à vos vues, via un dictionnaire Python.

The path() function can take an optional third argument which should be a dictionary of extra keyword arguments to pass to the view function.

Par exemple :

from django.urls import path
from . import views

urlpatterns = [
    path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]

In this example, for a request to /blog/2005/, Django will call views.year_archive(request, year=2005, foo='bar').

Cette technique est utilisée dans le système de syndication pour passer des métadonnées et des options aux vues.

Gestion des confilts

Il est possible d’avoir un motif d’URL qui capture des paramètres nommés, et qui passe aussi des paramètres ayant les mêmes noms dans son dictionnaire de paramètres supplémentaires. Quand c’est le cas, les paramètres du dictionnaire seront utilisés à la place des paramètres capturés dans l’URL.

Transmission de paramètres supplémentaires à include()

Similarly, you can pass extra options to include() and each line in the included URLconf will be passed the extra options.

Par exemple, ces deux ensembles de configurations d’URL sont fonctionnellement identiques :

Premier ensemble :

# main.py
from django.urls import include, path

urlpatterns = [
    path('blog/', include('inner'), {'blog_id': 3}),
]

# inner.py
from django.urls import path
from mysite import views

urlpatterns = [
    path('archive/', views.archive),
    path('about/', views.about),
]

Second ensemble :

# main.py
from django.urls import include, path
from mysite import views

urlpatterns = [
    path('blog/', include('inner')),
]

# inner.py
from django.urls import path

urlpatterns = [
    path('archive/', views.archive, {'blog_id': 3}),
    path('about/', views.about, {'blog_id': 3}),
]

Remarquez que les paramètres supplémentaires seront toujours passés à chaque élément de la configuration d’URL incluse, peu importe si la vue associée à l’élément accepte ces paramètres comme étant valides. C’est pour cette raison que cette technique est utile seulement lorsque vous êtes certain que toutes les vues de la configuration d’URL incluse acceptent les paramètres supplémentaires que vous passez.

Résolution inversée des URL

Un besoin courant quand on travaille sur un projet Django est d’avoir la possibilité d’obtenir des URL dans leur forme finale soit pour les incorporer dans du contenu généré (des URL vers des vues et des ressources, des URL montrées à l’utilisateur, etc.) ou pour gérer le flux de navigation côté serveur (redirections, etc.).

Il est très fortement suggéré d’éviter d’écrire des URL figées (une approche laborieuse, non extensible et sujette à l’erreur). Il est tout aussi dangereux de concevoir des mécanismes ad hoc capables de générer des URL identiques à celles décrites dans la configuration d’URL, risquant d’aboutir avec le temps à l’obtention d’URL obsolètes.

En d’autres termes, ce dont nous avons besoin est un mécanisme DRY (« ne pas se répéter »). L’un de ses avantages est de permettre l’évolution de l’organisation des URL sans avoir à parcourir le code source du projet pour remplacer les URL obsolètes.

L’information principale dont nous disposons pour récupérer une URL est une identification de la vue qui est chargée de la traiter (par exemple, son nom). Les autres informations nécessaires à la recherche de la bonne URL sont les types (positionnel, nommé) et les valeurs des paramètres de la vue.

Django met à disposition une solution qui fait en sorte que le système d’abstraction d’URL est le seul à connaître l’organisation des URL. Vous lui donnez votre configuration d’URL et vous pouvez ensuite l’utiliser dans les deux sens :

  • À partir d’une URL demandée par un utilisateur/navigateur, il appelle la vue Django concernée en lui passant tous les paramètres dont elle a besoin en extrayant les valeurs telles quelles de l’URL.
  • À partir de l’identification de la vue Django concernée ainsi que les valeurs des paramètres qui lui seraient passés, il renvoie l’URL associée.

Le premier correspond à l’utilisation dont nous avons parlé dans les sections précédentes. Le second correspond à ce qu’on appelle la résolution inversée des URL, la correspondance inverse d’URL, la recherche inverse d’URL, ou plus simplement l’inversion d’URL.

Django met à disposition des outils pour réaliser une inversion d’URL dans les différentes couches où les URL sont nécessaires :

  • Dans les gabarits : en utilisant la balise de gabarit url.
  • Dans le code Python : en utilisant la fonction reverse().
  • Dans le code plus abstrait amené à manipuler les URL des instances de modèle Django : la méthode get_absolute_url().

Exemples

Reprenons comme exemple cette ligne de configuration d’URL :

from django.urls import path

from . import views

urlpatterns = [
    #...
    path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
    #...
]

According to this design, the URL for the archive corresponding to year nnnn is /articles/<nnnn>/.

Vous pouvez obtenir ces URL dans les gabarits en utilisant :

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

Ou en Python :

from django.urls import reverse
from django.http import HttpResponseRedirect

def redirect_to_year(request):
    # ...
    year = 2006
    # ...
    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

Si, pour quelque raison que ce soit, vous décidez de changer l’URL à laquelle les archives annuelles d’articles sont sauvegardées, vous aurez seulement besoin de changer la ligne concernée dans la configuration d’URL.

Dans le cas où les vues ont un comportement générique, une relation N:1 peut exister entre les URL et les vues. Dans ces cas-là, le nom de la vue n’est pas un identifiant suffisant au moment où il s’agit d’utiliser l’inversion d’URL. Lisez la section suivante pour découvrir la solution qu’apporte Django à ce problème.

Nommage des motifs d’URL

Afin de pouvoir effectuer des inversions d’URL, il est nécessaire d’utiliser des motifs d’URL nommés comme vous pouvez le voir dans les exemples ci-dessus. La chaîne utilisée pour les noms des URL peut contenir tous les caractères que vous voulez. Vous n’êtes pas tenus d’utiliser des noms Python valables.

Lors du nommage des motifs d’URL, choisissez des noms qui ont peu de chances d’entrer en conflit avec ceux d’une autre application. Si vous appelez votre motif d’URL comment, et qu’une autre application fait la même chose, l’URL trouvée par reverse() dépend de la position du motif dans la liste urlpatterns du projet (le dernier gagne).

L’ajout d’un préfixe aux noms d’URL, peut-être dérivé du nom de l’application (comme monapp-comment au lieu de comment), permet de réduire les risques de collision.

Vous pouvez choisir délibérément le même nom d’URL qu’une autre application si vous souhaitez redéfinir une vue. Par exemple, un cas d’utilisation courant est de redéfinir LoginView. Certaines parties de Django et de nombreuses applications tierces supposent que cette vue répond au motif d’URL dont le nom est login. Si vous écrivez votre propre vue de connexion et que vous donnez le nom login à son URL, reverse() va trouver votre vue personnalisée pour autant qu’elle apparaisse après l’inclusion de django.contrib.auth.urls (le cas échéant) dans les motifs urlpatterns.

Il est aussi possible d’utiliser plusieurs fois le même nom dans les motifs d’URL s’ils diffèrent dans leurs paramètres. En plus du nom d’URL, reverse() recherche des correspondances en fonction du nombre de paramètres et du nom des paramètres nommés.

Les espaces de noms d’URL

Introduction

Les espaces de noms d’URL permettent la résolution inverse de motifs d’URL nommés de manière unique, même si différentes applications utilisent les mêmes noms d’URL. L’utilisation systématique d’URL avec espaces de noms est une bonne pratique que les applications tierces devraient adopter (comme cela a été fait dans le tutoriel). C’est aussi un moyen qui permet la résolution inverse quand plusieurs instances d’une application sont déployées. En d’autres termes, comme plusieurs instances d’une même application partagent les URL nommées, les espaces de noms fournissent un moyen de distinguer ces URL nommées.

Les applications Django qui font bon usage des espaces de noms d’URL peuvent être déployées plusieurs fois pour un même site. Par exemple, django.contrib.admin possède une classe AdminSite permettant de facilement déployer plus d’une instance de l’interface d’administration. Dans un exemple ultérieur, nous aborderons l’idée de déployer l’application polls du tutoriel à deux emplacements différents afin de pouvoir offrir la même fonctionnalité à deux audiences différentes (auteurs et éditeurs).

Un espace de noms d’URL se compose de deux parties, qui sont les deux des chaînes de caractères :

espace de noms d’application
Ceci définit le nom de l’application déployée. Chaque instance d’une même application possède le même espace de noms d’application. Par exemple, l’application d’administration de Django possède l’espace de noms d’application 'admin', comme l’on peut s’y attendre.
espace de noms d’instance
Ceci identifie une instance particulière d’une application. Les espaces de noms d’instance doivent être uniques dans tout un projet. Cependant, un espace de noms d’instance peut être identique à l’espace de noms d’application. C’est utilisé pour identifier l’instance par défaut d’une application. Par exemple, l’instance par défaut du site d’administration de Django possède l’espace de noms d’instance 'admin'.

Les URL avec espace de noms sont identifiées par l’opérateur ':'. Par exemple, la page d’accueil principale de l’application d’administration est référencée par 'admin:index'. Cela indique une URL nommée 'index' dans un espace de noms 'admin'.

Les espaces de noms peuvent aussi être imbriqués. L’URL nommée 'sports:polls:index' recherche un motif nommé 'index' dans l’espace de noms 'polls', lui-même défini à l’intérieur de l’espace de noms de premier niveau 'sports'.

Résolution inverse des URL avec espaces de noms

Lorsqu’il reçoit une URL avec espace de noms à résoudre (par ex. 'polls:index'), Django partage le nom complet en segments et effectue la recherche suivante :

  1. Premièrement, Django cherche un espace de noms d’application correspondant (dans cet exemple, 'polls'). Cela produira une liste d’instances de cette application.

  2. Si une application courante est définie, Django trouve et renvoie le résolveur d’URL de cette instance. L’application courante peut être définie avec le paramètre current_app de la fonction reverse().

    La balise de gabarit url utilise l’espace de noms de la vue actuellement résolue comne application courante dans un RequestContext. Vous pouvez outrepasser cette valeur par défaut en définissant l’application courante dans l’attribut request.current_app.

  3. S’il n’existe pas d’application courante, Django cherche une instance d’application par défaut. Celle-ci correspond à l’instance dont l”espace de noms d’instance est identique à l”espace de noms d’application (dans cet exemple, une instance de polls appelée 'polls').

  4. S’il n’existe pas d’instance d’application par défaut, Django sélectionne la dernière instance déployée de l’application, quel que soit son nom d’instance.

  5. Si l’espace de noms indiqué ne correspond pas à un espace de noms d’application à l’étape 1, Django effectue une recherche directe d’espace de noms en tant qu”espace de noms d’instance.

S’il existe des espaces de noms imbriqués, ces étapes sont répétées pour chaque partie de l’espace de noms jusqu’à ce qu’il ne reste plus que le nom de la vue comme élément non résolu. Le nom de vue est ensuite résolu comme URL dans l’espace de noms qui a été trouvé.

Exemple

Pour voir en action cette stratégie de résolution, considérez l’exemple de deux instances de l’application polls du tutoriel : l’une appelée 'author-polls' et l’autre 'publisher-polls'. Supposons que l’on ait amélioré cette application afin qu’elle prenne en considération l’espace de noms de l’instance lors de la création et de l’affichage des sondages.

urls.py
from django.urls import include, path

urlpatterns = [
    path('author-polls/', include('polls.urls', namespace='author-polls')),
    path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]
polls/urls.py
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    ...
]

Avec cette configuration, les recherches suivantes sont possibles :

  • Si l’une des instances est courante, c’est-à-dire que nous construisons la page de détail dans l’instance 'author-polls', 'polls:index' est résolu à la page d’accueil de l’instance 'author-polls'. C’est-à-dire que les deux expressions suivantes produiront "/author-polls/".

    Dans la méthode d’une vue fondée sur les classes :

    reverse('polls:index', current_app=self.request.resolver_match.namespace)
    

    et dans le gabarit :

    {% url 'polls:index' %}
    
  • S’il n’existe pas d’instance courante, par exemple si nous produisons une page quelque part ailleurs sur le site, 'polls:index' est résolu en rapport avec l’instance polls inscrite en dernier. Comme il n’y a pas d’instance par défaut (espace de noms d’instance 'polls'), c’est la dernière instance inscrite de polls qui est utilisée. Cela sera 'publisher-polls' car c’est celle qui est déclarée en dernier dans les motifs d’URL urlpatterns.

  • 'author-polls:index' est toujours résolu comme page d’accueil de l’instance 'author-polls' (et de même pour 'publisher-polls').

S’il y avait aussi une instance par défaut, nommée 'polls', la seule chose qui change par rapport à ci-dessus est que quand il n’y a pas d’instance courante (le deuxième cas ci-dessus), 'polls:index' est résolu à la page d’accueil de l’instance par défaut, et non pas de l’instance déclarée en dernier dans les motifs d’URL urlpatterns.

Espaces de noms d’URL et configurations d’URL incluses

Les espaces de noms d’application des configurations d’URL incluses peuvent être définis de deux manières.

Firstly, you can set an app_name attribute in the included URLconf module, at the same level as the urlpatterns attribute. You have to pass the actual module, or a string reference to the module, to include(), not the list of urlpatterns itself.

polls/urls.py
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    ...
]
urls.py
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
]

Les URL définies dans polls.urls auront un espace de noms d’application polls.

Secondly, you can include an object that contains embedded namespace data. If you include() a list of path() or re_path() instances, the URLs contained in that object will be added to the global namespace. However, you can also include() a 2-tuple containing:

(<list of path()/re_path() instances>, <application namespace>)

Par exemple :

from django.urls import include, path

from . import views

polls_patterns = ([
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
], 'polls')

urlpatterns = [
    path('polls/', include(polls_patterns)),
]

Cela va inclure les motifs d’URL nommés dans l’espace de noms d’application donné.

The instance namespace can be specified using the namespace argument to include(). If the instance namespace is not specified, it will default to the included URLconf’s application namespace. This means it will also be the default instance for that namespace.

Back to Top