¿Cómo obtener el nombre de la URL actual usando Django?

90

Tengo que crear una URL de forma dinámica de acuerdo con la URL actual. Usar la {% url %}etiqueta es la forma más fácil de hacerlo, pero necesito el nombre de la URL actual para generar la nueva de forma dinámica.

¿Cómo puedo adjuntar el nombre de la URL a la urlconf que conduce a la vista actual?

EDITAR: Sé que puedo crear manualmente la URL usando, get_absolute_urlpero prefiero evitarlo ya que es parte de una conferencia y me gustaría demostrar solo una forma de crear URL.

Los alumnos saben cómo utilizar {% url %}. Se sabe que se enfrentan a un problema cuando tienen que generar una URL más completa basada en la actual. La forma más sencilla es {% url %}volver a utilizarla , con algunas variaciones. Dado que hemos nombrado url, necesitamos saber cómo obtener el nombre de la URL que llamó a la vista actual.

EDICIÓN 2: otro caso de uso es mostrar partes de la plantilla base de manera diferente según la plantilla base. Hay otras formas de hacerlo (usando CSS y {% block%}, pero a veces es bueno poder eliminar la etiqueta de la entrada del menú de base.html si el nombre de la vista coincide con el enlace.

e-satis
fuente
6
Seguí encontrando esta pregunta mientras buscaba una forma de generar la URL actual y absoluta a través de una etiqueta de plantilla ... si también está buscando eso, es:{{ request.get_full_path }}
Dolph

Respuestas:

134

No sé cuánto tiempo ha sido esta característica parte de Django, pero como muestra el siguiente artículo , se puede lograr de la siguiente manera en la vista:

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

Si necesita eso en cada plantilla, escribir una solicitud de plantilla puede ser apropiado.

Editar: APLICANDO LA NUEVA ACTUALIZACIÓN DE DJANGO

Siguiendo la actualización actual de Django:

Django 1.10 ( enlace )

La importación desde el django.core.urlresolversmódulo está obsoleta a favor de su nueva ubicación,django.urls

Django 2.0 ( enlace )

El django.core.urlresolversmódulo se elimina a favor de su nueva ubicación django.urls,.

Por lo tanto, la forma correcta de hacerlo es así:

from django.urls import resolve
current_url = resolve(request.path_info).url_name
Lukas Bünger
fuente
¿Por qué? Hasta donde he entendido tu pregunta, una parte vital de ella era cómo lograr "Ya que hemos nombrado la URL, necesitamos saber cómo obtener el nombre de la URL que llamó a la vista actual" ...
Lukas Bünger
1
En realidad, lukas, estaba de mal humor ese día y descarté tu respuesta de manera completamente arbitraria. Pido disculpas, porque esta es realmente la respuesta correcta. Voy a editarlo para hacerlo más evidente.
e-satis
8
resolve()no se puede resolver si le pasa una cadena de consulta y simplemente genera un 404. get_full_path()devuelve la ruta y la cadena de consulta. Necesitará usar resolve(request.path_info).
Can Burak Çilingir
¿Qué currentsucede si no es la URL la que tiene que resolverse, sino, por ejemplo, la URL a la que va a redirigir el usuario? ¿Cuál es una forma más genérica de lograr esto? La respuesta de Conley Owens tiene una pista, pero prefiero no reinventar la rueda si dicha rueda ya existe en Django bajo el capó.
Hassan Baig
Esto no parece funcionar para las URL traducibles con i18n_patterns
guival
109

A partir de Django 1.5, se puede acceder a esto desde el objeto de solicitud

    current_url = request.resolver_match.url_name

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

Bharatwaaj
fuente
Cuando puse esto en un procesador de contexto funcionó, pero este extraño error se mostró en la consola:AttributeError: 'WSGIRequest' object has no attribute 'resolver_match'
fjsj
2
El 'resolver_match' se agrega al objeto de solicitud solo después de llamar a todo el middleware de solicitud. Ahí es cuando se resuelven las URL. Por lo tanto, solo puede acceder desde la vista del middleware en adelante. (funciones process_view del middleware). No estará disponible en las funciones de solicitud de middleware. (funciones process_request de middleware).
Bharathwaaj
.view_namesi necesita el espacio de nombres
27

Para aquellos que usan espacios de nombres en sus patrones de URL, entonces puede estar interesado en el nombre de URL de espacios de nombres de la solicitud. En este caso, Django lo llamó en su view_namelugar.

request.resolver_match.view_name

# return: <namespace>:<url name>
Yeo
fuente
Gracias, pero esta es más o menos una copia de la respuesta anterior de @ dariusz-niespodziany, ¿no? stackoverflow.com/a/31931833/1450294
Michael Scheper
5
Si no tiene espacio de nombres, urls.pyentonces @ dariusz-niespodziany es inmediatamente reverse-able. Pero si usa un espacio de nombres, entonces resolver_match.url_nameno es directamente reverse-able. Por lo tanto, debe agregar el espacio de nombres usted mismo. Entonces, en lugar de hacerlo usted mismo, Django ya configuró el .view_nameal inicializar.
Yeo
15

Esto se puede lograr mediante:

    request.resolver_match.url_name

Django> 1.8

niespodd
fuente
4

Aclaración de la pregunta: "En una vista, ¿cómo se obtiene el nombre de un patrón de URL que apunta a él, asumiendo que existe exactamente uno de esos patrones de URL"?

Esto puede ser deseable por las razones indicadas: desde dentro de la vista, queremos una forma SECA de obtener una URL para la misma vista (no queremos tener que conocer nuestro propio nombre de patrón de URL).

Respuesta corta: No es lo suficientemente simple como para impartir tu clase, pero podría ser algo divertido para ti hacer en una hora o dos y vomitar en GitHub.

Si realmente quisiera hacer esto, tendría que crear una subclase de RegexURLResolver y modificar el método de resolución para devolver el patrón coincidente (del cual puede obtener el nombre del patrón) en lugar de los pares de vista y palabra clave / valor. http://code.djangoproject.com/browser/django/trunk/django/core/urlresolvers.py#L142

Luego, podría crear un decorador o quizás un middleware más apropiado que use esta subclase para obtener el nombre del patrón y almacenar ese valor en algún lugar de la solicitud para que las vistas puedan usarlo.

Si realmente quiere hacer eso y tiene algún problema, hágamelo saber y probablemente pueda ayudar.

Para su clase, simplemente les pediría que codificaran el nombre del patrón en la vista o plantilla. Creo que esta es la forma aceptable de hacerlo.

Actualización: cuanto más pienso en esto, más desalentaría intentar obtener un nombre de patrón de URL en una vista. Los parámetros de urlpattern son bastante independientes de los parámetros de la vista a la que apuntan. Si desea apuntar a una URL determinada, debe saber cómo funciona el patrón de URL, no solo cómo funciona la vista. Si necesita saber cómo funciona el patrón de URL, es posible que también tenga que saber el nombre del patrón de URL.

Conley Owens
fuente
3

Solo inténtalo request.path. Eso obtendrá la ruta actual que se solicita.

Abhishek Iyengar
fuente
1

No está claro a partir de tu pregunta, pero http://docs.djangoproject.com/en/dev/topics/http/urls/ probablemente te dará una explicación de lo que buscas.

Especialmente útil para notar cómo Django procesa las solicitudes:

Cuando un usuario solicita una página de su sitio con tecnología Django, este es el algoritmo que sigue el sistema para determinar qué código Python ejecutar:

  1. Django determina el módulo raíz URLconf que se utilizará. Normalmente, este es el valor de la configuración ROOT_URLCONF, pero si el objeto HttpRequest entrante tiene un atributo llamado urlconf (establecido por el procesamiento de solicitudes de middleware), su valor se utilizará en lugar de la configuración ROOT_URLCONF.
  2. Django carga ese módulo de Python y busca la variable urlpatterns. Esta debería ser una lista de Python, en el formato devuelto por la función django.conf.urls.defaults.patterns ().
  3. Django recorre cada patrón de URL, en orden, y se detiene en el primero que coincide con la URL solicitada.
  4. Una vez que una de las expresiones regulares coincide, Django importa y llama a la vista dada, que es una función de Python simple. La vista recibe una HttpRequest como su primer argumento y cualquier valor capturado en la expresión regular como argumentos restantes.

Si solo busca la ruta completa, puede probar:

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

Espero que eso ayude, indica cómo usar el módulo URLconf y, con suerte, le ayudará a orientarlo en la dirección correcta.

Mark Mayo
fuente
Gracias, pero lo sé :-) Agregué algunas explicaciones para evitar malentendidos.
e-satis