Despachante de URL

Um esquema de URL elegante e limpo, é um detalhes importante em uma aplicação Web de alta quailidade, O Django deixa que você especifique URLs como queira, sem limitações do “framework”.

Não requer .php ou .cgi, e certamente nada de nonsense 0,2097,1-1-1928,00.

Veja o Cool URIs don’t change, por Tim Berners-Lee criador da World Wide Web, para argumentos excelentes sobre porque URLs devem ser limpas e usáveis.

Visão Geral

Para definir URLs para uma app, você cria um módulo Python informalmente chamado de URLconf (Configuração de URL). Este módulo é código Python puro e é um simples mapa entre padrões de formatos de URL (expressões regulares simples) para funções Python (suas “Views”).

Este mapemaneto pode ser tão curto ou tão longo quanto necessário. Pode referenciar outros mapeamentos. E, porque é código Python puro, pode ser construído dinamicamente.

O Django também fornece uma maneira de traduzir URLs de acordo com a língua ativa. Veja o documentação de internacionaliação para mais finromação.

Como o Django processa uma requisição

Quando um usuário requisita uma página do seu site feito em Django, este é o algoritmo que o sistema segue para determinar qual código Python executar:

  1. O Django determina o módulo URLConf raiz a ser usado. Ordinariamente, este é o valor da definição do ROOT_URLCONF, mas se o objeto HttpRequest que está chegando tem um atributo urlconf (definido pelo “middleware”), o valor definido por ele será usado no lugar da definição do ROOT_URLCONF.

  2. O Django carrega aquele módulo Python e procura por uma varável urlpatterns. Esta deve ser uma lista Python de instâncias do tipo django.conf.urls.url().

  3. O Django passa por cada padrão de URL definido, na ordem, e para na primieira que combina com a URL requisitada.

  4. Uma vez que uma das expressões regulares combina, o Django importa e executa a “view”, a qual é uma simples função Python (ou uma “Views” baseadas em classe). A “view” recebe os seguintes argumento:

    • Uma instância do HttpRequest.

    • Se a expressão regular não retorna grupos nominados, então as partes encontradas pela expressão regular são fornecidas como argumentos posicionais.

    • Os argumentos nominados são na verdade qualquer grupo nomeado encontrado pela expressão regular, sobrescritos por qualquer argumento especificado no argumento kwargs opcional para a django.conf.urls.url().

  5. Se nenhuma regex combina, ou se uma exceção é emitida durante qualquer ponto deste processo, o Django invoca a “view” apropriada de manipulação de erro. Veja Error handling abaixo.

Exemplo

Aqui um exemplo de URLconf:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

Notas:

  • Para capturar um valor vindo da URL, apenas coloque parentesis ao seu redor.

  • Não há necessidade de adicionar uma barra na frente, porque toda URL tem isso. Por exemplo, é ^articles, e não ^/articles.

  • O ``‘r’``na frente de cada string de expressão regular é opcional mas recomendado. Isso diz ao Django que uma string é ‘’bruta’’ – que nada na string deve ser interpretado. Veja Dive Into Python’s explanation.

Requisições de exemplo:

  • Uma requisição para /articles/2005/03/ deve combinar com a terceira entrada na lista. o Django de chamar a função views.month_archive(request, '2005', '03').

  • /articles/2005/3/ não deve encontrar nenhum padrão de URL, porque a terceira entrada na lista requer dois digitos para o mês.

  • /articles/2003/ deve combinar com o primeiro padrão de formatp na lista, não o segundo, porque os padrões são testado em ordem, e o primeiro é o que primeiro atende ao padrão. Sinta-se livre para explorar a ordem e inserir casos especiais como este. Aqui, o Django deve chamar a função views.special_case_2003(request)

  • /articles/2003 não deve combinar com nenhum destes padrões, porque cada padrão de formato requer que a URL termine com uma barra.

  • /articles/2003/03/03/ deve combinar com o último padrão. o Django deve chamar a função views.article_detail(request, '2003', '03', '03').

Grupos nominados

O exemplo acima usou grupos simples e não nominados (através de parentesis) de expressões regulares para capturar as partes da URL e passa-las como argumentos posicionais para a “view”. Em usos mais avançados, é possível usar grupos nomeados de expressões regulares para capturar partes da URL e passa-los como argumentos nomeados para a “view”

Em expressões regulares em Python, a sintaxe para grupos nominados de expressões regulares é (?P<name>pattern), onde name é o nome do grupo e pattern é algum padrão de formato para combinar.

Aqui é o exemplo acima de URLconf, rescrito para usar grupos nominados:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

Ele atende a mesma coisa que o exemplo anterior, com uma diferença sutil: Os valores capturados são passados para funções “view” como argumentos nomeados ao invés de argumentos posicionais. Por exemplo:

  • Uma requisição para /articles/2005/03/ deve chamar a função views.month_archive(request, year='2005', month='03'), ao invés de views.month_archive(request, '2005', '03').

  • Uma requisição para /articles/2003/03/03/ deve chamar a função views.article_detail(request, year='2003', month='03', day='03').

Na prática, isso quer dizer que seu URLconfs são um pouco mais explícitos e menos inclinado a bugs de ordem de argumentos – e você pode reordenar os argumentos nas definições de suas funções “views”. Claro, estes benefício vem com um preço; alguns desenvolvedores acham a sintaxe de grupos nominados feia e muito verbosa.

O algoritmo de combinação/agrupamento

Aqui o algoritmo que o interpretador do URLconf segue, com respeito a grupos nominados vs grupos não nomeados em uma expressão regular:

  1. Se houver qualquer argumento nominado, ele usará estes, ignorando argumentos não nomeados.

  2. De outra forma, ele passará todos argumentos não nominados como argumentos posicionais.

Em ambos os casos, qualquer argumento nomeado extra que tenha sido dado Passing extra options to view functions (abaixo) também será passado para a “view”.

Onde e o que o URLconf procura

O URLconf procura na URL requisitada, como uma string Python normal. Isso não inclui parâmetros GET ou POST, ou o nome do domínio.

Por exemplo em uma requisição para https://www.example.com/myapp/, o URLconf irá olhar para myapp/.

Em uma requisição para https://www.example.com/myapp/?page=3, o URLconf irá olhar para myapp/.

O URLconf nÃo olha para o método da requisição. Em outras palavras, todas os métodos de requisições – POST, GET, HEAD, etc. – serão roteados para a mesma função para a mesma URL.

Argumentos capturados são sempre strings.

Cada argumento capturado é enviado para a “view” como uma string Python plana, não importando que tipo de combinação a expressão regular faz. Por exemplo, nesta linha do URLconf:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
...o argumento year passado para views.year_archive() será ums atring,

não um inteiro, apesar que o [0-9]{4} somente irá combinar strings de inteiros.

Especificando agumentos padrão para “view”

Uma truque conveniente é especificar parâmetros padrão para seus argumentos de “views”. Aqui um exemplo de URLconf e “view”:

# URLconf
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

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

No exemplo acima, ambos os padrões de URL apontam para a mesma “view” – views.page – mas o primeiro padrão não captura nada vindo da URL. Se o primeiro padrão combinar, a função page() irá usar o argumento padrão "1" para num. Se o segundo padrão combinar, page() irá usar qualquer valor para num que tenha sido capturado pela regex.

Performance

Cada empressão regular dentro do urlpatterns é compilada na primeira vez que é acessad. Isso torna o sistema tremendamente rápido.

Sintaxe da variável urlpatterns

A urlpatterns deve ser uma lista de instâncias url().

Manipulação de erros

Quando o Django não pode encontrar uma regex que combine com a URL requisitada, ou quando uma exceção é emitida, o Django irá invocar uma “view” de manipulação de erro.

As “views” para usar nestes casos são especificadas por quatro variáveis. O valor padrão destas variáveis deve bastar para a maioria dos projetos, mas uma maior persoanlização é possível sobrescrevendo seus valores padrão.

Veja a documentação em Personalizando “views” de erros para detalhes completos.

Tais valores podem ser definidos dentro do sey URLconf raiz. Definir estes valores em qualquer outro URLconf não irá ter nenhum efeito.

Os valores devm ser “executáveis”, ou strings que representam o caminho Python completo para a “view” que deve ser chamada para lidar com o condição de erro.

As variáveis são:

Incluindo outros URLconfs

Em qualquer ponto, seus ``urlpatterns``podem “inluir” outros módulos URLconf. Isso essencialmente enraiza um conjunto de URLs embaixo de outros.

Por exemplo, aqui um enxerto de URLconf para o próprio Django website. Isso inclui várias outras URLconfs:

from django.conf.urls import include, url

urlpatterns = [
    # ... snip ...
    url(r'^community/', include('django_website.aggregator.urls')),
    url(r'^contact/', include('django_website.contact.urls')),
    # ... snip ...
]

Note que as expressões regulares neste exemplo não tem o $ (caracter que indica término de string) mas inclui uma barra à direita. Sempre que o Django encontra a ìnclude()` (django.conf.urls.include()), ele corta fora qualquer parte da URL encontrada até aquele ponto e envia a string restante para o URLconf incluído para processamento futuro.

Outra possibilidade é incluir padrões de URL adicionais usando uma lista de instâncias de url(). Por exemplo, considere esta URLconf:

from django.conf.urls import include, url

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

extra_patterns = [
    url(r'^reports/$', credit_views.report),
    url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),
    url(r'^charge/$', credit_views.charge),
]

urlpatterns = [
    url(r'^$', main_views.homepage),
    url(r'^help/', include('apps.help.urls')),
    url(r'^credit/', include(extra_patterns)),
]

Neste exemplo, a URL /credit/reports/ será manipulada pela view Django credit_views.report().

Isso pode ser usado para remover redundâncias de URLconf onde um único prefixo de padrão é usado repetidamente. Por exemplo, considere o URLconf:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/history/$', views.history),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/edit/$', views.edit),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/discuss/$', views.discuss),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/permissions/$', views.permissions),
]

Podemos melhorar isso começando o caminho comum com um prefixo e agrupando os sufixos que diferem:

from django.conf.urls import include, url
from . import views

urlpatterns = [
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
        url(r'^history/$', views.history),
        url(r'^edit/$', views.edit),
        url(r'^discuss/$', views.discuss),
        url(r'^permissions/$', views.permissions),
    ])),
]

Parâmetros capturados

Um URLconf que foi inluído recebe qualquer parâmetro capturado vindos dos URLconfs pais, logo o seguinte exemplo é válido:

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

urlpatterns = [
    url(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
]

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

urlpatterns = [
    url(r'^$', views.blog.index),
    url(r'^archive/$', views.blog.archive),
]

No exemplo acima, a variável "username" é capturada e passada para o URLconf incluído, como esperado.

Argumentos aninhados

Expressões regulares permitem argumentos aninhados, e o Django irá resolvê-los e passá-los para a “view”. Quando usar o “reverse”, o Django tentará preencher todos os argumentos capturados fora, ignorando qualquer argumento aninhado capturado. Considere o seguinte padrão de URL o qual opcionalmente pega um arumento “page”:

from django.conf.urls import url

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

Ambos os padrões usam argumento aninhados e irão resolver: por exemplo, blog/page-2/ irá resultar em na combinação com blog_articles com dois argumentos posicionais: page-2/ e 2. O segundo padrão para comments irá encontrar comments/page-2/ com argumento nomeado page_number definido como 2. O argumento mais externo neste caso é um argumento não capturado (?:...).

A “view” blog_articles precisa do argumento mais externo para que seja possível acessá-la de maneira reversa, neste caso page-2/ ou nenhum argumento , enquanto ue comments pode ser acessado reversamente com argumento nenhum ou com um valor para page_number.

Argumentos aninhados criam um acomplamento forte entre os argumentos da “view” e sua URL como ilustrado pelo blog_articles: a “view” recebe parte da URL (``page-2/”) ao invés de somente o valor que a “view” está interessada. Este acoplamento é ainda mais evidente quando acessando reversamente, já que para acessá-la reversamente precisa passar uma parte da URL ao invés de somente o número da página.

Como regra geral, apenas capturar os valores que a “view” precisa para funcionar e usar argumentos não capturáveis quando a expressão regurlar precisar de um argumento mas que a “view” o ignora.

Passando opções extras para função “view”

URLconfs tem um gancho que deixa você passar argumentos extra par suas funções “view”, como um dicionário Python.

A função django.conf.urls.url() pode receber um terceiro argumento opcional o qual deve ser um dicionário de argumentos nomeados extra para passar para a função “view”.

Por exemplo:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

Neste exemplo, para uma requisição para /blog/2005/, o Django irá chamar views.year_archive(request, year='2005', foo='bar').

Esta técnica é usada no syndication framework para passar metadados e opções para as “views”.

Lidando com conflitos

É possível ter um padrão de formato de URL o qual captura argumentos nominados, e também passa argumentos com os mesmos nomes neste dicionário de argumentos extras. Quando isso acontece, o argumento no dicionário serão usados no lugar dos argumentos capturados na URL.

Passando opções extra para o include()

De maneira similar, você pode passar opções extra para a include(). Quando se passa opções extras para a include(), a cada linha inclída na URLconf lhe será passada as opções extras.

Por exemplo, estas duas definições de URLconf são funcionamente idênticas:

Definição um:

# main.py
from django.conf.urls import include, url

urlpatterns = [
    url(r'^blog/', include('inner'), {'blogid': 3}),
]

# inner.py
from django.conf.urls import url
from mysite import views

urlpatterns = [
    url(r'^archive/$', views.archive),
    url(r'^about/$', views.about),
]

Definição dois:

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

urlpatterns = [
    url(r'^blog/', include('inner')),
]

# inner.py
from django.conf.urls import url

urlpatterns = [
    url(r'^archive/$', views.archive, {'blogid': 3}),
    url(r'^about/$', views.about, {'blogid': 3}),
]

Note que as opções extra serão sempre passadas para cada linha do URLconf incluído, independente se a “view” aceita estas opções como válidas. Por esta razão, essa técnica é somente útil se você estiver certo que cada “view” no URLconf incluído aceita as opções extras que estão sendo passadas.

A resolução reversa de URLs

Uma necessidade comum quando trabalhando com um projeto Django é a possibilidade de obter URLs na sua forma final, seja para adicioná-lo em um conteúdo gerado (“views” e ativos de URLs, URLs a serem mostradas para o usuário, etc.) ou para lidar com o fluxo de navegação no lado do servidor (redirecionamentos, etc).

É altamente desejável evitar escrever URLs diretamente no código (uma estratégia trabalhosa, não-escalável e propensa a erros). Igualmente perigoso é conceber mecânismos pontuais para gerar URLs que sejam paralelos as especificações descritas no URLconf, o que pode resultar na produção de URLs que se tornem desatualizadas ao passar do tempo.

Em outras palavras, o que é preciso é um mecênismo enxuto (“DRY”). Entre outras vantagens isso permitiria a evolução da definição de URL sem ter que passar por todo o código do projeto para procurar e substituir URLs desatualizadas.

O primeiro pedaço de infomação que temos disponível para chegar a uma URL é uma identificação (ex.: o nome) da “view” responsável por lidar com ela. Outras partes de informação que necessariamente deve participar da busca pela URL correta são os tipos (posicional, nomeado) e valores dos argumentos da “view”.

O Django fornece uma solução tal que o mapeador de URL é o único reposritório de definição de URL. Você o alimenta com seu URLconf e então este pode ser usado em ambas as direções:

  • Começando com uma URL requisitada pelo usuário/navegador Web, ele chama a “view” Django correta fornecendo quaisquer argumentos que esta necessite e com os valores extraídos da URL.

  • Começando com a identificação da “view” Django correspondente mais os valores dos argumentos que poderiam ser passados a ela, obten-se a URL associada.

O primeiro caso é o uso que estivemos discutindo na seção anterior. O segundo é o que é conhecido como resolução reversa de URLs, combinação reversa de URL, filtro reverso de URL, ou simplesmente URL reversa.

O Django fornece ferramentas para realizar a reversão de URL que vá de encontro com as diferentes camadas onde URLs são necessárias:

  • Em “templates”: usando a tag de template url.

  • In Python code: Using the reverse() function.
  • EM código de nível mais alto relacionado à manipulação de URLs de instâncias de modelos Django: o método get_absolute_url().

Exemplos

Considere novamente essa entrada do URLconf:

from django.conf.urls import url

from . import views

urlpatterns = [
    #...
    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
    #...
]

De acordo com esta definição, a URL para o “archice” correspondente ao ano nnnn é /articles/nnnn/.

Você pode obtê-la no código de template usando:

<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 em código 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,)))

Se, por algum motivo, foi decidido que a URL onde conteúdo de arquivos de artigos anuais são publicados deve ser alterados, então é deve-se alterar somente a entrada no URLconf.

Em alguns cenários onde “views” são de natureza genérica, talvez exista um relacionamento muitos-para-um entre URLs e “views”. Para estes casos o nome da “view” não é um identificador bom o suficiente para identificá-los quando chega a hora de usar a URL reversa. Leia a próxima seção para conhecer a solução que o Django fornece pra isso.

Nomeando padrões de formato de URL

De modo a realizar uma URL reversa, é necessário usar **padrões de URL nominadas* como feito no exemplo acima. A string usada para o nome da URL pode conter qualquer caracter que queira. Você não está restrito a nomes válidos em Python.

Quando nomear seus padrões de formato de URL, tenha certeza de usar nomes que não são parecidos e que podem conflitar com quaisquer outras escolhas de nomes de outras aplicações. Se você chama seu padrão de formato de URL de comment, e outro aplicação fizer o mesmo, não há garantias sobre qual URL será inserida no seu templates quando usar este nome.

Colocando um prefixo nos nomes de suas URL, talvez derivado do nome de sua aplicação, irá diminuir as chances de colisão. Recomendamos algo como myapp-comment ao invés de comment.

Domínio de nomes de URL

Introdução

Nomes de domínios de URL possibilitam a você exclusividade ao reverter os padrões de formato de URL nominados, mesmo que uma aplicação diferente use os mesmos nomes para URL. É uma boa prática para aplicações de terceiros sempre usar URLs dentro de um nome de domínio (como fizemos no tutorial). De mpodo similar, isso também permite a você usar o mode reverso de URLs se múltiplas intâncias de uma aplicação for implantada. Em outras palavras, se múltiplas instâncias de uma única aplicação irá compartilhar URLs nominada, os nomes de domínios fornecem uma maneira de manter essas URLs nominadas separadas.

As aplicações Django que fazem uso correto do “namespacing” da URL podem ser instaladas em produção mais de uma vez para um mesmo site. Por exemplo django.contrib.admin tem uma classe AdminSite a qual permite facilmente instalar mais de uma instância do admin. Em um exemplo a seguir, iremos discutir a idéia de instalar a aplicação “polls” do tutorial em dois locais diferentes de modo que podemos servir as mesmas funcionalidades para dois públicos diferentes (autores e editores).

Um nome de domínio de URL é formado por duas partes, sendo ambas do tipo strings:

Nome de domínio da aplicação

Este descreve o nome da aplicação que está sendo implantada. Cada instância de uma única aplicação terá o mesmo nome de domínio de apliacação. Por exemlo, a aplicação de administração do Django tem previsivelmente seu nome de domínio de aplicação como sendo 'admin'.

Nome de domínio de instância

Isso identifica uma instância específica de uma aplicação. Nomes de domínio de instância devem ser únicos dentro de todo o seu projeto. Contudo, um nome de domínio de uma intância pode ser o mesmo que o nome de domínio da sua aplicação. Isso é usado para especificar uma instância padrão da aplicação. Por exemplo, a instância padrão do administrador do Django tem 'admin' como seu nome de domínio de instância.

Nome de domínios de URLs são especificados usando o operador ':'. Por exemplo, a página principal da aplicação “admin” é referenciada usando 'admin:index'. Isso indica um nome de domínio do 'admin', e uma URL moninada de 'índice'.

Nomes de domínio podem ser aninhados. A URL nominada 'sports:polls:index' poderia procurar por um padrão de formato chamado 'index' no nome de domínio 'polls' que é ele próprio definido dentro do nome de domínio de nível superior 'sports'.

Revertendo URLs com nomes de domínios

Quando dada uma URL com nome de domínio (ex.: 'polls:index') para resolver, o Django divide em partes o nome totalmente qualificado e então trás o seguinte filtro:

  1. Primeiro, o Django procura por uma application namespace que combine (neste exemplo, 'polls'). Isso irá produzir uma lista de instâncias daquela aplicação.

  2. If there is a current application defined, Django finds and returns the URL resolver for that instance. The current application can be specified with the current_app argument to the reverse() function.

    A tag de template url usa o nome de domínio da view corrente resolvida como a aplicação corrente em uma RequestContext. Você pode sobrescrever seu padrão definindo a aplicação corrente no atributo request.current_app.

    Changed in Django 1.9:

    Previamente, a tag de “template” url não usava o nome de domínio da “view” resolvida correntemente e você tinha que definir o atributo current_app na requisição.

  3. Se não há aplicação corrente, o Django procura por um instância de aplicação padrão. A instância da aplicação padrão é a instância que tem um instance namespace que combine com o application namespace (neste exemplo, uma instância de polls``chamada ``'polls').

  4. Se não uma instância padrão de aplicação, o Django irá usar a última instância instalada da aplicação, não importando qual seja o nome desta instância.

  5. Se o nome de domínio não combina com application namespace no passo 1, o Django irá tentar um filtro direto do nome de domínio como um instance namespace.

Se há nomes de domínios aninhados, estes passos são repetidos para cada parte do nome de domínio até que somente o nome da “view” esteja não resolvido. O nome da “view” será então resolvido em uma URL dentro do nome de domínio no qual foi encontrado.

Exemplo

Para mostrar essa estratégia de resolução em ação, considere um exemplo de duas instâncias da aplicação polls do tutorial: uma chamada 'authors-polls' e uma chamada 'publisher-poll'. Assuma que tenhamos melhorado esta aplicação de modo que ela leve em consideração o nome de domínio da instância quando criar e mostrar as enquetes (‘polls’).

urls.py
from django.conf.urls import include, url

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

from . import views

app_name = 'polls'
urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
    ...
]

Usando esta definição, os seguintes filtros são possíveis:

  • Se uma das intâncias é a corrente - digamos, se estivermos renderizando a página de detalhes da instância 'author-polls' - 'polls:index' será resolvido para a página de índice da instância 'author-polls'; isto é, ambos os seguintes irão resultar em "/author-polls/".

    No método de uma “view” baseada em classe:

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

    e no “template”:

    {% url 'polls:index' %}
    
  • Se não houver uma instância corrente - digamos, se estivermos renderizando uma págna el algum outro lugar do site - 'polls:index' será resolvido para a última instância registrada de polls. Desde que não haja uma instância padrão (nome de domínio de instância 'polls'), a última instância de polls registrada será usada. Essa deve ser 'publisher-polls' já que foi declarada por último no urlpatterns.

  • 'author-polls:index' sempre irá resolver para a página de índice da instância 'author-polls' (da mesma forma para 'publisher-polls') .

Se havia também uma instância padrão - isto é, uma instância nominada 'polls' - a única mudança do exemplo acima seria no caso onde não há intância corrente (o segundo item na lista acima). Neste caso 'polls:index' seria resolvido para a página de índice da intância padrão ao invés da instância declarada por último no urlpatterns.

Domínios de nomes de URL e URLconfs incluídos

o Domínio dos nomes de aplicação de URLconfs cinludídos podem ser especificados de dois modos.

Primeiramente, você pode definir um atributo app_ame na módulo URLconf incluído, no mesmo nível que o atributo urlspatterns. você tem que passar o módulo atual, ou uma string de referência para o módulo, para include(), não a própria lista do urlpatterns.

polls/urls.py
from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
    ...
]
urls.py
from django.conf.urls import include, url

urlpatterns = [
    url(r'^polls/', include('polls.urls')),
]

As URLs definidas em polls.urls terão um nome de domínio como polls.

Segundamente, você pode incluir um objeto que contém dados do nome de domínio embutid. Se você fizer um include() de uma lista de instâncias de url(), as URLs contidas naquele objeto serão adicionadas no nome de domínio global. Contudo, você pode também fazer um include() de uma tupla de dois parâmetros contendo:

(<list of url() instances>, <application namespace>)

Por exemplo:

from django.conf.urls import include, url

from . import views

polls_patterns = ([
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
], 'polls')

urlpatterns = [
    url(r'^polls/', include(polls_patterns)),
]

Isso irá incluir o nome do padrão de formato de URL nomeado dentro do nome de domínio da dada aplicação.

O nome de domínio da instância pode ser especificado usando o argumento namespace da include(). Se o nome de domínio da instância não for especificado, este usará o padrão do nome de domínio da aplicação do URLconf incluído. Isso quer dizer que ele será também a intância padrão para aquele nome de domínio.

Changed in Django 1.9:

Em versões anteriores, você tinha que especificar ambos, o nome de domínio da aplicação e o nome de domínio da intância em um único local, ou passando-os como parâmetros para include() ou incluindo uma tupla de 3 parâmetros contendo (<inst&ancias de lista de url()>, <nome de domínio da aplicação>, <nome de domínio da instância>).

Back to Top