Obtenir l'URL d'administration Django pour un objet

168

Avant Django 1.0, il y avait un moyen simple d'obtenir l'URL d'administration d'un objet, et j'avais écrit un petit filtre que j'utiliserais comme ceci: <a href="{{ object|admin_url }}" .... > ... </a>

Fondamentalement, j'utilisais la fonction d'inversion d'URL avec le nom de la vue 'django.contrib.admin.views.main.change_stage'

reverse( 'django.contrib.admin.views.main.change_stage', args=[app_label, model_name, object_id] )

pour obtenir l'url.

Comme vous l'avez peut-être deviné, j'essaie de mettre à jour vers la dernière version de Django, et c'est l'un des obstacles que j'ai rencontrés, cette méthode pour obtenir l'URL d'administration ne fonctionne plus.

Comment puis-je faire cela dans django 1.0? (ou 1.1 d'ailleurs, car j'essaye de mettre à jour vers la dernière version du svn).

hasen
la source

Réponses:

61

J'ai eu un problème similaire où j'essayais d'appeler reverse('admin_index')et recevais constamment des django.core.urlresolvers.NoReverseMatcherreurs.

Il s'avère que j'avais l'ancien format des URL d'administrateur dans mon fichier urls.py.

J'avais ceci dans mes urlpatterns:

(r'^admin/(.*)', admin.site.root),

ce qui fait fonctionner les écrans d'administration, mais c'est la façon obsolète de le faire. J'avais besoin de le changer pour ceci:

(r'^admin/', include(admin.site.urls) ),

Une fois que j'ai fait cela, tous les avantages promis dans les documents sur les URL d'administration inversées ont commencé à fonctionner.

bskinnersf
la source
Génial, cela a corrigé un autre problème que j'avais avec la méthode get_urls () de ModelAdmin qui n'était pas appelée. Merci!
Arnaud
8
meilleure URL pour ce problème: docs.djangoproject.com/en/dev/ref/contrib/admin/…
Dingo
4
Cette "réponse" n'est pas correcte, elle montre simplement comment ajouter correctement l'application d'administration à votre application, ce qui a résolu un problème différent que l'auteur avait. La vraie réponse à la question réelle est ci-dessous - de markmuetz
Declan Shanaghy
En outre, vous devez avoir une interface d'administration enregistrée pour le modèle, sinon l'URL n'existera pas.
Flimm le
412

Vous pouvez utiliser le résolveur d'URL directement dans un modèle, il n'est pas nécessaire d'écrire votre propre filtre. Par exemple

{% url 'admin:index' %}

{% url 'admin:polls_choice_add' %}

{% url 'admin:polls_choice_change' choice.id %}

{% url 'admin:polls_choice_changelist' %}

Réf: Documentation

Markmuetz
la source
1
markmuetz - Est-ce que c'est dans la documentation officielle de Django quelque part? (comment utiliser les URL inversées d'administration dans les modèles)? Sinon, ça devrait l'être.
shacker
7
shacker - Tout est dans la documentation ... mais pas au même endroit. La balise de modèle "url" est documentée ici . Dans la section "Nouveau dans Django 1.1:", la documentation indique que les URL à espaces de noms conviennent et vous renvoie à la section sur les espaces de noms d'URL . Coller tout cela vous permet de référencer facilement l'application d'administration dans des modèles. NB Je me souviens que les documents étaient différents lorsque j'ai écrit la réponse.
markmuetz
3
Savez-vous comment obtenir un lien vers la «liste» des choix? Exemple: si "{% url admin: polls_choice_add%}" donne "/ admin / polls / choice / add" quel serait l'équivalent qui me donnerait "/ admin / polls / choice"?
DarwinSurvivor
2
{% url admin: polls_choice_changelist%} renvoie l'url '/ admin / polls / choice'
luc
35
L'inversion d'une URL d'administrateur est actuellement entièrement documentée ici https://docs.djangoproject.com/en/dev/ref/contrib/admin/#reversing-admin-urls
Josh Russo
101
from django.core.urlresolvers import reverse
def url_to_edit_object(obj):
  url = reverse('admin:%s_%s_change' % (obj._meta.app_label,  obj._meta.model_name),  args=[obj.id] )
  return u'<a href="%s">Edit %s</a>' % (url,  obj.__unicode__())

Ceci est similaire à la solution de hansen_j sauf qu'elle utilise les espaces de noms d'url , admin: étant l'espace de noms d'application par défaut de l'administrateur.

Mike Ramirez
la source
3
Merci, ça aide. Une chose que je changerais: utiliser args=[object.pk]au lieu de args=[object.id]. Il couvre le cas plus courant, lorsque le champ de clé primaire a un autre nom que id.
tige
5
Bonne réponse. Pour info, toute personne utilisant un django plus récent devra changer object._meta.module_name en object._meta.model_name
Jagu
Un grand merci d'un débutant django. object._meta.app_labellaissez-moi finalement obtenir le nom de la propre application d'authentification de django. C'est auth, par exemple, reverse(admin:auth_user_change, args=[object.id])pour passer à la page de changement d'utilisateur
Gret
2
Assurez-vous de changer l'objet en obj. Ce type est en train d'écrire un symbole intégré réservé.
Kevin Parker
17

Il existe un autre moyen pour les versions ultérieures, par exemple dans la 1.10 :

{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>

optsest quelque chose comme mymodelinstance._metaouMyModelClass._meta

Un problème est que vous ne pouvez pas accéder aux attributs de soulignement directement dans les modèles Django (comme {{ myinstance._meta }}), vous devez donc passer l' optsobjet à partir de la vue en tant que contexte de modèle.

Anentropique
la source
2
L'URL de la documentation a changé! Voir: docs.djangoproject.com/en/1.9/ref/contrib/admin/…
Wim Feijen
12

Essentiellement la même que la réponse de Mike Ramirez, mais plus simple et plus proche en stylistique de la get_absolute_urlméthode standard de django :

def get_admin_url(self):
    return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name),
                   args=[self.id])
Antony Hatchkins
la source
11

Pour django pré 1.1, c'est simple (pour l'instance de site d'administration par défaut):

reverse('admin_%s_%s_change' % (app_label, model_name), args=(object_id,))
Alex Koshelev
la source
8
Avec le nouvel espace de noms, c'est admin:% s_% s_change
Teebes
3

Si vous utilisez 1.0, essayez de créer une étiquette de modèle personnalisée qui ressemble à ceci:

def adminpageurl(object, link=None):
    if link is None:
        link = object
    return "<a href=\"/admin/%s/%s/%d\">%s</a>" % (
        instance._meta.app_label,
        instance._meta.module_name,
        instance.id,
        link,
    )

puis utilisez simplement {% adminpageurl my_object%} dans votre template (n'oubliez pas de charger d'abord le templatetag)

DarwinSurvivor
la source
1

J'ai résolu ce problème en changeant l'expression en:

reverse( 'django-admin', args=["%s/%s/%s/" % (app_label, model_name, object_id)] )

Cela nécessite / suppose que la racine de l'url conf a un nom pour le gestionnaire d'url "admin", principalement ce nom est "django-admin",

c'est à dire dans la racine de l'url conf:

url(r'^admin/(.*)', admin.site.root, name='django-admin'),

Il semble fonctionner, mais je ne suis pas sûr de sa propreté.

hasen
la source
2
Cela fonctionne pour 1.0, mais ne fonctionnera pas pour 1.1, qui a une meilleure solution: voir la réponse d'Alex Koshelev.
Carl Meyer
En fait, je l'ai essayé et cela n'a pas fonctionné, et il a dit que c'était pour 1.0, non?
hasen
La syntaxe a changé dans la version 1.1 avec l'introduction de l'espace de noms des URL: docs.djangoproject.com/en/dev/topics/http/urls/…
sleepyjames
-1

Voici une autre option, en utilisant des modèles:

Créez un modèle de base (ou ajoutez simplement la méthode admin_link à un modèle particulier)

class CommonModel(models.Model):
    def admin_link(self):
        if self.pk:
            return mark_safe(u'<a target="_blank" href="../../../%s/%s/%s/">%s</a>' % (self._meta.app_label,
                    self._meta.object_name.lower(), self.pk, self))
        else:
            return mark_safe(u'')
    class Meta:
        abstract = True

Hériter de ce modèle de base

   class User(CommonModel):
        username = models.CharField(max_length=765)
        password = models.CharField(max_length=192)

Utilisez-le dans un modèle

{{ user.admin_link }}

Ou voir

user.admin_link()
Ian Cohen
la source
2
Je ne pense pas que ce soit une bonne solution. Construire une URL avec un formatage de chaîne est une mauvaise habitude. Veuillez utiliser reverse ().
guettli