Como obter o nome da url atual usando Django?

91

Tenho que construir um url dinamicamente de acordo com o url atual. Usar a {% url %}tag é a maneira mais fácil de fazer isso, mas preciso do nome do url atual para gerar o novo dinamicamente.

Como posso obter o nome do url anexado ao urlconf que leva à visualização atual?

EDITAR: Sei que posso get_absolute_urlcriar manualmente a url usando, mas prefiro evitá-la, pois é parte de uma aula e gostaria de demonstrar apenas uma maneira de construir urls.

Os alunos sabem como usar {% url %}. Eles sabem que enfrentam um problema quando precisam gerar uma url mais completa com base na atual. A maneira mais fácil é usar {% url %}novamente, com algumas variações. Já que nomeamos url, precisamos saber como obter o nome do url que chamou a visualização atual.

EDIT 2: outro caso de uso é exibir partes do template base de forma diferente de acordo com o template base. Existem outras maneiras de fazer isso (usando CSS e {% block%}, mas às vezes é bom poder remover a tag da entrada do menu de base.html se o nome da visualização corresponder ao link.

e-satis
fonte
6
Continuei encontrando essa pergunta enquanto procurava uma maneira de gerar o URL absoluto atual por meio de uma tag de modelo ... se você também estiver procurando por isso, é:{{ request.get_full_path }}
Dolph

Respostas:

134

Não sei há quanto tempo esse recurso faz parte do Django, mas como mostra o artigo a seguir , ele pode ser obtido da seguinte forma na visualização:

   from django.core.urlresolvers import resolve
   current_url = resolve(request.path_info).url_name

Se você precisar disso em cada modelo, escrever uma solicitação de modelo pode ser apropriado.

Editar: APLICANDO A NOVA ATUALIZAÇÃO DO DJANGO

Seguindo a atualização atual do Django:

Django 1.10 ( link )

A importação do django.core.urlresolversmódulo foi descontinuada em favor de seu novo local,django.urls

Django 2.0 ( link )

O django.core.urlresolversmódulo é removido em favor de seu novo local django.urls,.

Assim, a maneira certa de fazer é assim:

from django.urls import resolve
current_url = resolve(request.path_info).url_name
Lukas Bünger
fonte
Por quê? Pelo que entendi sua pergunta, uma parte vital dela era como alcançar "Como nomeamos url, precisamos saber como obter o nome do url que chamou a exibição atual." ...
Lukas Bünger
1
Na verdade, lukas, eu estava mal-humorado naquele dia e descartei sua resposta arbitrariamente. Peço desculpas, porque esta é realmente a resposta certa. vou editá-lo para torná-lo mais antigo.
e-satis de
8
resolve()não pode ser resolvido se você passar uma string de consulta e simplesmente gerar um erro 404. get_full_path()retorna o caminho e a string de consulta. Você precisará usar resolve(request.path_info).
Can Burak Çilingir
E se não for o currenturl que precisa ser resolvido, mas, digamos, aquele para o qual o usuário irá redirecionar? Qual é a maneira mais genérica de fazer isso? A resposta de Conley Owens tem uma pista, mas prefiro não reinventar a roda se ela já existir no Django sob o capô.
Hassan Baig
Isso não parece funcionar para urls traduzíveis com i18n_patterns
guival
110

A partir do Django 1.5, isso pode ser acessado a partir do objeto de solicitação

current_url = request.resolver_match.url_name

Se você quiser o nome do url junto com o namespace

current_url = request.resolver_match.view_name

https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.resolver_match

Bharathwaaj
fonte
Quando coloquei isso em um processador de contexto funcionou, mas este erro estranho foi mostrado no console:AttributeError: 'WSGIRequest' object has no attribute 'resolver_match'
fjsj
2
O 'resolver_match' é adicionado ao objeto de solicitação somente depois de chamar todo o middleware de solicitação. É quando os urls estão sendo resolvidos. Portanto, você pode acessar apenas a partir do view middleware. (funções process_view de middleware). Não estará disponível nas funções de middleware de solicitação. (funções process_request do middleware).
Bharathwaaj
.view_namese você precisar do namespace
29

Para aqueles que usam namespace para seus padrões de url, você pode estar interessado no nome de url com namespace da solicitação. Nesse caso, o Django o chamou view_name.

request.resolver_match.view_name

# return: <namespace>:<url name>
Yeo
fonte
Obrigado, mas isso é basicamente um truque da resposta anterior de @ dariusz-niespodziany, não é? stackoverflow.com/a/31931833/1450294
Michael Scheper
5
Se você não fez o namespace, urls.pyentão @ dariusz-niespodziany é imediatamente reversedisponível. Mas se você estiver usando um namespace, então resolver_match.url_namenão é diretamente reversedisponível. Portanto, você mesmo precisa anexar o namespace. Então, em vez de fazer você mesmo, o Django já configurou o .view_namena inicialização.
Yeo,
16

Isso pode ser feito por meio de:

    request.resolver_match.url_name

Django> 1.8

niespodd
fonte
4

Esclarecimento da pergunta: "Em uma visão, como você obtém o nome de um urlpattern que aponta para ele, assumindo que existe exatamente um urlpattern."

Isso pode ser desejável pelas razões apresentadas: de dentro da visão, queremos uma maneira SECA de obter um url para a mesma visão (não queremos saber o nome do nosso próprio urlpattern).

Resposta curta: Na verdade, não é simples o suficiente para ensinar sua classe, mas pode ser uma coisa divertida para você fazer em uma ou duas horas e vomitar no GitHub.

Se você realmente quisesse fazer isso, teria que criar uma subclasse de RegexURLResolver e modificar o método de resolução para retornar o padrão correspondente (do qual você pode obter o nome do padrão) em vez dos pares de visualização e palavra-chave / valor. http://code.djangoproject.com/browser/django/trunk/django/core/urlresolvers.py#L142

Você poderia então criar um decorador ou talvez mais apropriadamente um middleware que use essa subclasse para obter o nome do padrão e armazenar esse valor em algum lugar na solicitação para que as visualizações possam usá-lo.

Se você realmente deseja fazer isso e se depara com alguns problemas, me avise e provavelmente posso ajudar.

Para sua classe, gostaria apenas que eles codificassem o nome do padrão na visualização ou no modelo. Eu acredito que essa é a maneira aceitável de fazer isso.

Atualização: quanto mais penso sobre isso, mais desencorajaria a tentativa de obter um nome de urlpattern em uma exibição. Os parâmetros do urlpattern são bastante independentes dos parâmetros da visão para a qual apontam. Se você deseja apontar para um determinado url, você precisa saber como o urlpattern funciona, não apenas como a visualização funciona. Se você precisa saber como funciona o urlpattern, também pode precisar saber o nome do urlpattern.

Conley Owens
fonte
3

Apenas tente request.path. Isso obterá o caminho atual que está sendo solicitado.

Abhishek Iyengar
fonte
1

Sua pergunta não está clara, mas http://docs.djangoproject.com/en/dev/topics/http/urls/ provavelmente fornecerá uma explicação para o que você está procurando.

Especialmente útil observar como o Django processa solicitações:

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

  1. Django determina o módulo URLconf root a ser usado. Normalmente, este é o valor da configuração ROOT_URLCONF, mas se o objeto HttpRequest de entrada tiver um atributo chamado urlconf (definido pelo processamento de solicitação de middleware), seu valor será usado no lugar da configuração ROOT_URLCONF.
  2. Django carrega esse módulo Python e procura pela variável urlpatterns. Esta deve ser uma lista Python, no formato retornado pela função django.conf.urls.defaults.patterns ().
  3. O Django percorre cada padrão de URL, em ordem, e para no primeiro que corresponda à URL solicitada.
  4. Assim que uma das expressões regulares corresponder, o Django importa e chama a visualização fornecida, que é uma função Python simples. A visualização recebe um HttpRequest como seu primeiro argumento e quaisquer valores capturados na regex como argumentos restantes.

Se você estiver apenas atrás do caminho completo, pode tentar:

http://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.get_full_path

Espero que ajude - indica como usar o módulo URLconf e espero que ajude a apontar a direção certa.

Mark Mayo
fonte
Obrigado, mas eu sei que :-) adicionei algumas explicações para evitar mal-entendidos.
e-satis,