Comment obtenir le nom actuel de l'url en utilisant Django?

90

Je dois créer une URL de manière dynamique en fonction de l'url actuelle. Utiliser la {% url %}balise est le moyen le plus simple de le faire, mais j'ai besoin du nom actuel de l'url pour générer le nouveau dynamiquement.

Comment puis-je obtenir le nom de l'url attaché à l'urlconf qui mène à la vue actuelle?

EDIT: Je sais que je peux créer manuellement l'URL en utilisant, get_absolute_urlmais je préfère l'éviter car cela fait partie d'une conférence et je voudrais montrer qu'une seule façon de créer des URL.

Les étudiants savent comment utiliser {% url %}. Ils savent qu'ils font face à un problème lorsqu'ils doivent générer une URL plus complète basée sur l'actuelle. Le moyen le plus simple est de l'utiliser à {% url %}nouveau, avec quelques variantes. Puisque nous avons nommé url, nous devons savoir comment obtenir le nom de l'url qui a appelé la vue actuelle.

EDIT 2: un autre cas d'utilisation est d'afficher différemment des parties du modèle de base en fonction du modèle de base. Il y a d'autres façons de le faire (en utilisant CSS et {% block%}, mais parfois, il est tout simplement agréable de pouvoir supprimer la balise de l'entrée de menu de base.html si le nom de la vue correspond au lien.

e-satis
la source
6
J'ai continué à trouver cette question en cherchant un moyen de générer l' URL absolue actuelle via une balise de modèle ... si vous recherchez également cela, c'est:{{ request.get_full_path }}
Dolph

Réponses:

134

Je ne sais pas depuis combien de temps cette fonctionnalité fait partie de Django, mais comme le montre l' article suivant , cela peut être réalisé comme suit dans la vue:

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

Si vous en avez besoin dans chaque modèle, la rédaction d'une demande de modèle peut être appropriée.

Edit: APPLIQUER UNE NOUVELLE MISE À JOUR DJANGO

Suite à la mise à jour actuelle de Django:

Django 1.10 ( lien )

Importation depuis le django.core.urlresolvers module est déconseillée au profit de son nouvel emplacement,django.urls

Django 2.0 ( lien )

le django.core.urlresolvers module est retiré en faveur de son nouvel emplacement, django.urls.

Ainsi, la bonne façon de faire est la suivante:

from django.urls import resolve
current_url = resolve(request.path_info).url_name
Lukas Bünger
la source
Pourquoi? Pour autant que j'ai compris votre question, une partie essentielle de celle-ci était de savoir comment réaliser "Depuis que nous avons nommé l'url, nous devons savoir comment obtenir le nom de l'url qui a appelé la vue actuelle." ...
Lukas Bünger
1
En fait, j'étais grognon ce jour-là et j'ai écarté votre réponse de manière complètement arbitraire. Je m'excuse, car c'est en fait la bonne réponse. je vais le modifier pour le rendre plus évident.
e-satis
8
resolve()ne peut pas résoudre si vous lui passez une chaîne de requête et déclenche simplement un 404. get_full_path()renvoie le chemin et la chaîne de requête. Vous devrez utiliser resolve(request.path_info).
Can Burak Çilingir
Et si ce n'est pas l' currentURL qui doit être résolue, mais, par exemple, celle vers laquelle un utilisateur va rediriger? Quelle est la manière la plus générique d'y parvenir? La réponse de Conley Owens a un indice, mais je préfère ne pas réinventer la roue si ladite roue existe déjà à Django sous le capot.
Hassan Baig
Cela ne semble pas fonctionner pour les URL traduisibles avec i18n_patterns
guival
109

À partir de Django 1.5, cela est accessible à partir de l'objet de requête

    current_url = request.resolver_match.url_name

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

Bharathwaaj
la source
Quand j'ai mis cela dans un processeur de contexte, cela a fonctionné, mais cette erreur étrange a été affichée dans la console:AttributeError: 'WSGIRequest' object has no attribute 'resolver_match'
fjsj
2
Le 'resolver_match' est ajouté à l'objet de requête uniquement après avoir appelé tous les middleware de requête. C'est à ce moment que les URL sont résolues. Vous ne pouvez donc accéder qu'à partir du middleware View. (fonctions process_view du middleware). Il ne sera pas disponible dans les fonctions de middleware de requête. (fonctions process_request du middleware).
Bharathwaaj
.view_namesi vous avez besoin de l'espace de noms
27

Pour ceux qui attribuent un espace de nom à leurs modèles d'URL, vous pouvez être intéressé par le nom d'url avec espace de nom de la requête. Dans ce cas, Django l'a appelé à la view_nameplace.

request.resolver_match.view_name

# return: <namespace>:<url name>
Yeo
la source
Merci, mais c'est à peu près une dupe de la réponse précédente de @ dariusz-niespodziany, n'est-ce pas? stackoverflow.com/a/31931833/1450294
Michael Scheper
5
Si vous n'avez pas d'espace de noms, urls.pyalors @ dariusz-niespodziany est immédiatement reverse-able. Mais si vous utilisez un espace de noms, alors resolver_match.url_namen'est pas directement reverse-able. Vous devez donc ajouter vous-même l'espace de noms. Donc, au lieu de le faire vous-même, Django a déjà défini le .view_namelors de l'initialisation.
Yeo
15

Ceci peut être réalisé via:

    request.resolver_match.url_name

Django> 1,8

niespodd
la source
4

Clarification de la question: "Dans une vue, comment obtenir le nom d'un urlpattern qui pointe dessus, en supposant qu'il existe exactement un tel urlpattern."

Cela peut être souhaitable pour les raisons indiquées: à partir de la vue, nous voulons un moyen DRY d'obtenir une URL vers la même vue (nous ne voulons pas avoir à connaître notre propre nom de modèle d'url).

Réponse courte: Ce n'est pas vraiment assez simple d'enseigner à votre classe, mais cela pourrait être une chose amusante à faire dans une heure ou deux et à vomir sur GitHub.

Si vous vouliez vraiment faire cela, vous devrez sous-classer RegexURLResolver et modifier la méthode de résolution pour renvoyer le modèle correspondant (à partir duquel vous pouvez obtenir le nom du modèle) au lieu des paires vue et mot-clé / valeur. http://code.djangoproject.com/browser/django/trunk/django/core/urlresolvers.py#L142

Vous pouvez ensuite créer un décorateur ou peut-être plus approprié un middleware qui utilise cette sous-classe pour obtenir le nom du modèle et stocker cette valeur quelque part dans la requête afin que les vues puissent l'utiliser.

Si vous voulez vraiment faire cela et que vous rencontrez des problèmes, faites-le moi savoir et je pourrai probablement vous aider.

Pour votre classe, je leur demanderais simplement de coder en dur le nom du modèle dans la vue ou le modèle. Je pense que c'est la manière acceptable de le faire.

Mise à jour: plus j'y pense, plus je découragerais d'essayer d'obtenir un nom de modèle d'URL dans une vue. Les paramètres urlpattern sont assez indépendants des paramètres de la vue qu'ils pointent. Si vous souhaitez pointer vers une certaine URL, vous devez savoir comment fonctionne le modèle d'url, pas seulement comment la vue fonctionne. Si vous avez besoin de savoir comment fonctionne le modèle d'url, vous pourriez aussi avoir besoin de connaître le nom du modèle d'url.

Conley Owens
la source
3

Essayez juste request.path. Cela obtiendra le chemin actuel demandé.

Abhishek Iyengar
la source
1

Ce n'est pas clair d'après votre question, mais http://docs.djangoproject.com/en/dev/topics/http/urls/ fournira probablement une explication à ce que vous recherchez.

Particulièrement utile pour noter comment Django traite les requêtes:

Lorsqu'un utilisateur demande une page à votre site alimenté par Django, c'est l'algorithme que le système suit pour déterminer le code Python à exécuter:

  1. Django détermine le module URLconf racine à utiliser. Habituellement, il s'agit de la valeur du paramètre ROOT_URLCONF, mais si l'objet HttpRequest entrant a un attribut appelé urlconf (défini par le traitement de la requête middleware), sa valeur sera utilisée à la place du paramètre ROOT_URLCONF.
  2. Django charge ce module Python et recherche les variables urlpatterns. Il doit s'agir d'une liste Python, au format renvoyé par la fonction django.conf.urls.defaults.patterns ().
  3. Django parcourt chaque modèle d'URL, dans l'ordre, et s'arrête au premier qui correspond à l'URL demandée.
  4. Une fois qu'une des expressions régulières correspond, Django importe et appelle la vue donnée, qui est une simple fonction Python. La vue reçoit une HttpRequest comme premier argument et toutes les valeurs capturées dans l'expression régulière comme arguments restants.

Si vous êtes juste après le chemin complet, vous pouvez essayer:

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

J'espère que cela vous aidera - cela indique comment utiliser le module URLconf et, espérons-le, vous aidera à vous orienter dans la bonne direction.

Mark Mayo
la source
Merci mais je sais que :-) J'ai ajouté quelques explications pour éviter les malentendus.
e-satis