Obtener la URL de administrador de Django para un objeto

168

Antes de Django 1.0 había una manera fácil de obtener la URL de administrador de un objeto, y había escrito un pequeño filtro que usaría así: <a href="{{ object|admin_url }}" .... > ... </a>

Básicamente estaba usando la función de inversión de URL con el nombre de la vista siendo 'django.contrib.admin.views.main.change_stage'

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

para obtener la url.

Como habrás adivinado, estoy tratando de actualizar a la última versión de Django, y este es uno de los obstáculos que encontré, ese método para obtener la URL de administrador ya no funciona.

¿Cómo puedo hacer esto en django 1.0? (o 1.1 para el caso, ya que estoy tratando de actualizar a la última versión en el svn).

Hasen
fuente

Respuestas:

61

Tuve un problema similar en el que intentaba llamar reverse('admin_index')y constantemente recibía django.core.urlresolvers.NoReverseMatcherrores.

Resulta que tenía las URL de administrador de formato antiguo en mi archivo urls.py.

Tenía esto en mis patrones de url:

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

que hace que funcionen las pantallas de administrador pero es la forma desaprobada de hacerlo. Necesitaba cambiarlo a esto:

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

Una vez que hice eso, toda la bondad prometida en los documentos de URL de administración inversa comenzó a funcionar.

bskinnersf
fuente
Impresionante, esto solucionó otro problema que estaba teniendo con el método get_urls () de ModelAdmin que no se llamaba. ¡Gracias!
Arnaud
8
mejor url para este problema: docs.djangoproject.com/en/dev/ref/contrib/admin/…
Dingo
44
Esta "respuesta" no es correcta, solo muestra cómo agregar correctamente la aplicación de administración a su aplicación, lo que resolvió un problema diferente que tenía el autor. La respuesta real a la pregunta real está abajo: de markmuetz
Declan Shanaghy, el
Además, debe tener una interfaz de administrador registrada para el modelo; de lo contrario, la URL no existirá.
Flimm
412

Puede usar el solucionador de URL directamente en una plantilla, no hay necesidad de escribir su propio filtro. P.ej

{% url 'admin:index' %}

{% url 'admin:polls_choice_add' %}

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

{% url 'admin:polls_choice_changelist' %}

Ref: Documentación

markmuetz
fuente
1
markmuetz - ¿Está esto en los documentos oficiales de Django en alguna parte? (¿Cómo usar las URL inversas del administrador en las plantillas)? Si no, debe ser.
Shacker
77
Shacker: todo está en los documentos ... pero no en un solo lugar. La etiqueta de la plantilla "url" se documenta aquí . En la sección "Nuevo en Django 1.1:" los documentos dicen que las URL de espacios de nombres están bien y lo dirigen a la sección de espacios de nombres de URL . Pegar todo junto le permite hacer referencia a la aplicación de administración fácilmente en plantillas. Nota: recuerdo que los documentos eran diferentes cuando escribí la respuesta.
markmuetz
3
¿Sabes cómo obtener un enlace a la "lista" de opciones? Ejemplo: si "{% url admin: polls_choice_add%}" da "/ admin / polls / choice / add" ¿cuál sería el equivalente que me daría "/ admin / polls / choice"?
DarwinSurvivor
2
{% url admin: polls_choice_changelist%} devuelve la url '/ admin / polls / choice'
luc
35
Invertir una URL de administrador está actualmente completamente documentado aquí 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__())

Esto es similar a la solución de hansen_j, excepto que utiliza espacios de nombres de URL , admin: es el espacio de nombres de la aplicación predeterminada del administrador.

Mike Ramirez
fuente
3
Gracias, ayuda. Una cosa que cambiaría: usar en args=[object.pk]lugar de args=[object.id]. Cubre el caso más común, cuando el campo de clave primaria tiene otro nombre que id.
acechar
55
Buena respuesta. Para su información, cualquier persona que use un django más reciente deberá cambiar object._meta.module_name a object._meta.model_name
Jagu
Muchas gracias de un novato de Django. object._meta.app_labeldéjame finalmente obtener el nombre de la propia aplicación de autenticación de django. Es auth, por ejemplo, reverse(admin:auth_user_change, args=[object.id])para saltar a la página de cambio de usuario
Gret
2
Asegúrese de cambiar el objeto a obj. Este tipo ha terminado de escribir un símbolo incorporado reservado.
Kevin Parker el
17

Hay otra forma para las versiones posteriores, por ejemplo en 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>

¿Dónde optsestá algo como mymodelinstance._metaoMyModelClass._meta

Un problema es que no puede acceder a los atributos de subrayado directamente en las plantillas de Django (como {{ myinstance._meta }}), por lo que debe pasar el optsobjeto desde la vista como contexto de plantilla.

Anéntrópico
fuente
2
¡La url de documentos ha cambiado! Ver: docs.djangoproject.com/en/1.9/ref/contrib/admin/…
Wim Feijen
12

Esencialmente lo mismo que la respuesta de Mike Ramirez, pero más simple y más cercano en estilística al get_absolute_urlmétodo estándar 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
fuente
11

Para pre 1.1 django es simple (para la instancia predeterminada del sitio de administración):

reverse('admin_%s_%s_change' % (app_label, model_name), args=(object_id,))
Alex Koshelev
fuente
8
Con el nuevo espacio de nombres es admin:% s_% s_change
Teebes
3

Si está utilizando 1.0, intente crear una etiqueta de plantilla personalizada que se vea así:

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,
    )

luego use {% adminpageurl my_object%} en su plantilla (no olvide cargar primero la etiqueta de plantilla)

DarwinSurvivor
fuente
1

Resolví esto cambiando la expresión a:

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

Esto requiere / asume que la raíz url conf tiene un nombre para el manejador de url "admin", principalmente ese nombre es "django-admin",

es decir, en la raíz url conf:

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

Parece estar funcionando, pero no estoy seguro de su limpieza.

Hasen
fuente
2
Esto funciona para 1.0, pero no funcionará para 1.1, que tiene una mejor solución: vea la respuesta de Alex Koshelev.
Carl Meyer
En realidad lo intenté y no funcionó, y él dijo que era por 1.0, ¿no?
hasen
La sintaxis ha cambiado en 1.1 con la introducción del espacio de nombres de URL: docs.djangoproject.com/en/dev/topics/http/urls/…
sleepyjames
-1

Aquí hay otra opción, usando modelos:

Cree un modelo base (o simplemente agregue el método admin_link a un modelo en particular)

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

Heredar de ese modelo base

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

Úselo en una plantilla

{{ user.admin_link }}

O ver

user.admin_link()
Ian Cohen
fuente
2
No creo que esta sea una buena solución. Construir una URL con formato de cadena es un mal hábito. Por favor use reverse ().
guettli