2010-03-18 17 views
37

Si un modelo Django contiene un campo de clave externa, y si ese campo se muestra en el modo de lista, a continuación, se muestra como texto, en lugar de mostrar un enlace que el objeto extraño .claves externas de visualización de la lista Django administrador

¿Es posible mostrar automáticamente todas las claves externas como enlaces en lugar de texto plano?

(por supuesto que es posible hacer eso en un campo por campo, pero ¿hay un método general?)

Ejemplo:

class Author(models.Model): 
    ... 

class Post(models.Model): 
    author = models.ForeignKey(Author) 

Ahora elija un ModelAdmin tal que el autor se muestra en modo de lista:

class PostAdmin(admin.ModelAdmin): 
    list_display = [..., 'author',...] 

Ahora en modo de lista, el campo de autor sólo se utilizan el método __unicode__ de la clase Author para mostrar el autor. Además de eso, quisiera un enlace apuntando a la url del autor correspondiente en el sitio de administración. ¿Es eso posible?

Método manual:

En aras de la exhaustividad, añadir el método manual. Sería añadir un método author_link en la clase PostAdmin:

def author_link(self, item): 
    return '<a href="../some/path/%d">%s</a>' % (item.id, unicode(item)) 
author_link.allow_tags = True 

que funcionará para ese campo en particular, sino que es no lo que quiero. Quiero un método general para lograr el mismo efecto. (Uno de los problemas es cómo descubrir automáticamente la ruta a un objeto en el sitio de administración de django.)

Respuesta

9

No creo que haya un mecanismo para hacer lo que desee automáticamente.

Pero en cuanto a la determinación de la ruta de acceso a una página de administración de edición basado en la identificación de un objeto, todo lo que necesita son dos tipos de información:

a) self.model._meta.app_label

b) self.model._meta.module_name

Entonces, por ejemplo, para ir a la página de edición para ese modelo puede hacer:

'../%s_%s_change/%d' % (self.model._meta.app_label, self.model._meta.module_name, item.id) 

Tome un vistazo a django.contrib.admin.options.ModelAdmin.get_urls para ver cómo lo hacen.

supongo que usted podría tener un invocable que toma un nombre de modelo y un identificador, crea un modelo del tipo especificado sólo para obtener la etiqueta y el nombre (sin necesidad de golpear la base de datos) y genera la URL a anterior.

¿Pero está seguro de que no puede obtener mediante el uso de las líneas? Sería una mejor interfaz de usuario tener todos los componentes relacionados en una sola página ...

Editar:

Inlines (vinculado a docs) permiten una interfaz de administración para mostrar una relación padre-hijo en una página en lugar de dividirla en dos.

En el ejemplo de publicación/autor que proporcionó, el uso de líneas en blanco significaría que la página para editar publicaciones también mostraría un formulario en línea para agregar/editar/eliminar autores. Mucho más natural para el usuario final.

Lo que puede hacer en su vista de lista de administración es crear un llamativo en el modelo de publicación que mostrará una lista de autores separados por comas. Por lo tanto, tendrá su vista de la lista de publicaciones que muestre los Autores adecuados y podrá editar los Autores asociados a una Publicación directamente en la interfaz de Administración de publicación.

+0

Gracias por esta respuesta! ¿Podría explicar el uso de inlines? ¿Cómo ayudaría eso? –

+0

@Olivier: Edité mi respuesta para indicarle la dirección correcta con respecto a las líneas. – cethegeek

18

Estaba buscando una solución al mismo problema y encontré esta pregunta ... terminé resolviéndola yo mismo. Es posible que el OP ya no esté interesado, pero esto aún podría ser útil para alguien.

from functools import partial 
from django.forms import MediaDefiningClass 

class ModelAdminWithForeignKeyLinksMetaclass(MediaDefiningClass): 

    def __getattr__(cls, name): 

     def foreign_key_link(instance, field): 
      target = getattr(instance, field) 
      return u'<a href="../../%s/%s/%d">%s</a>' % (
       target._meta.app_label, target._meta.module_name, target.id, unicode(target)) 

     if name[:8] == 'link_to_': 
      method = partial(foreign_key_link, field=name[8:]) 
      method.__name__ = name[8:] 
      method.allow_tags = True 
      setattr(cls, name, method) 
      return getattr(cls, name) 
     raise AttributeError 

class Book(models.Model): 
    title = models.CharField() 
    author = models.ForeignKey(Author) 

class BookAdmin(admin.ModelAdmin): 
    __metaclass__ = ModelAdminWithForeignKeyLinksMetaclass 

    list_display = ('title', 'link_to_author') 

Reemplace 'partial' con 'curry' de Django si no usa python> = 2.5.

+1

Itai Tavor, gracias por su respuesta, fue realmente triste, pero puede causar problemas, los detalles están en [mi respuesta a otra pregunta] (http://stackoverflow.com/questions/6473340/link-to-foreignkey- in-admin-causes-attributeerror-when-debug-is-false/7192721 # 7192721). – stepank

+0

Para mí, usar la ruta absoluta de %s funcionó mejor, ya que el enlace sería correcto cuando se está en la página de detalles del objeto, en lugar de solo en la página de la lista. –

+0

¿cuál es el parámetro para el método ModelAdminWith ...? No tengo un "MediaDefineClass" como forma? – Timo

Cuestiones relacionadas