2009-03-29 28 views
123

Antes de Django 1.0 no era una manera fácil de obtener la URL de administración de un objeto, y yo había escrito un pequeño filtro que me gustaría usar la siguiente manera: <a href="{{ object|admin_url }}" .... > ... </a>El conseguir Django URL de administración para un objeto

Básicamente yo estaba usando la función inversa de URL con el nombre de vista de ser '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).

Respuesta

48

Tuve un problema similar en el que me gustaría tratar de llamar reverse('admin_index') y estaba recibiendo constantemente django.core.urlresolvers.NoReverseMatch errores.

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

que tenía esto en mis urlpatterns:

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

que recibe las pantallas de administración de trabajo, pero es la forma obsoleta de hacerlo. Necesitaba cambiar a esto:

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

Una vez que lo hice, todo lo bueno que fue prometida en los documentos Reversing Admin URLs comenzó a trabajar.

+0

Impresionante, esto solucionó otro problema que estaba teniendo con el método get_urls() de ModelAdmin al que no se llamaba. ¡Gracias! – Arnaud

+7

mejor url para este problema: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#reversing-admin-urls – Dingo

+3

Esta "respuesta" no es correcta, solo muestra cómo agregar correctamente el administrador aplicación a su aplicación, que resolvió un problema diferente que tenía el autor. La respuesta real a la pregunta real es la siguiente: de markmuetz –

1

He resuelto esto cambiando la expresión de:

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

Esto requiere/asume que el conf URL raíz tiene un nombre para el "admin" controlador de URL, principalmente, que el nombre es "django-admin",

es decir, en la conf URL raíz:

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

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

+1

Esto funciona para 1.0, pero no funcionará para 1.1, que tiene una mejor solución: ver a Alex La respuesta de Koshelev. –

+0

En realidad lo probé y no funcionó, y dijo que es para 1.0, ¿no? – hasen

+0

La sintaxis ha cambiado en 1.1 con la introducción del espacio de nombres de url: http://docs.djangoproject.com/en/dev/topics/http/urls/#topics-http-reversing-url-namespaces – sleepyjames

9

Para pre 1.1 django es simple (por ejemplo, el sitio de administración por defecto):

reverse('admin_%s_%s_change' % (app_label, model_name), args=(object_id,)) 
+6

Con el nuevo espacio de nombres es admin:% s_% s_change – Teebes

3

Si está utilizando 1.0, intenta hacer una templatetag a medida que se parece a esto:

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

continuación, sólo tiene que utilizar {% adminpageurl mi_objeto%} en su plantilla (no se olvide de cargar el primer templatetag)

68
from django.core.urlresolvers import reverse 
def url_to_edit_object(object): 
    url = reverse('admin:%s_%s_change' %(object._meta.app_label, object._meta.model_name), args=[object.id]) 
    return u'<a href="%s">Edit %s</a>' %(url, object.__unicode__()) 

Esto es similar a la solución de hansen_j excepto que utiliza url namespaces, admin: ser espacio de nombres predeterminado de la aplicación del administrador.

+2

Gracias, ayuda. Una cosa que cambiaría: use 'args = [object.pk]' en lugar de 'args = [object.id]'. Cubre el caso más común, cuando el campo de clave primaria tiene otro nombre que 'id '. – stalk

+4

Buena respuesta. FYI cualquier persona que use un django más reciente necesitará cambiar object._meta.module_name to object._meta.model_name – Jagu

+0

Muchas gracias de un django novato. 'object._meta.app_label' finalmente me permite obtener el nombre de la 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

302

Puede usar la resolución de URL directamente en una plantilla, no es necesario que escriba 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: Documentation

+1

markmuetz - ¿Esto está en los documentos oficiales de Django en cualquier lugar? (cómo usar las URL inversas de administrador en las plantillas)? Si no, debe ser. – shacker

+6

shacker - Está todo en los documentos ... simplemente no en un solo lugar. La etiqueta de la plantilla "url" está documentada [aquí] (http://docs.djangoproject.com/en/1.2/ref/templates/builtins/#url). En la sección "Nuevo en Django 1.1:" los documentos dicen que las URL con el espacio de nombres están bien, y te apunta a [la sección de espacios de nombres de URL] (http://docs.djangoproject.com/en/1.2/topics/http/urls/# topics-http-reversing-url-namespaces). Pegarlo todo le permite hacer referencia fácilmente a la aplicación de administración en las plantillas. N.B Recuerdo que los documentos eran diferentes cuando escribí la respuesta. – markmuetz

+3

¿Sabes cómo obtener un enlace a la "lista" de opciones? Ejemplo: if "{% url admin: polls_choice_add%}" da "/ admin/polls/choice/add" ¿cuál sería el equivalente que me daría "/ admin/polls/choice"? – DarwinSurvivor

0

Aquí es otra opción, utilizando modelos:

Crear un modelo de base (o simplemente añadir 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 que el modelo de base

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

utilizarlo en una plantilla

{{ user.admin_link }} 

O view

user.admin_link() 
+0

No creo que esta sea una buena solución. Crear una URL con formato de cadena es un mal hábito. Por favor use reverse(). – guettli

11

Hay otro camino para las versiones posteriores, por ejemplo in 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 opts es algo así como mymodelinstance._meta o MyModelClass._meta

Uno de gotcha es que no se puede acceder subrayado atributos directamente en las plantillas de Django (como {{ myinstance._meta }}) por lo que debe pasar el objeto opts desde la vista como contexto de plantilla.

+2

¡La url de documentos ha cambiado! Ver: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#reversing-admin-urls –

7

En esencia, el mismo que la respuesta de Mike Ramírez, pero más simple y más cerca de la estilística a Django estándar get_absolute_url método:

def get_admin_url(self): 
    return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), 
        args=[self.id]) 
Cuestiones relacionadas