primary - Teclas foráneas en la lista de administración de django
foreign key django example (3)
Si un modelo de django contiene un campo de clave externa, y si ese campo se muestra en modo de lista, entonces aparece como texto , en lugar de mostrar un enlace al objeto extraño.
¿Es posible mostrar automáticamente todas las claves externas como enlaces en lugar de texto plano?
(por supuesto, es posible hacerlo campo por campo, pero ¿hay un método general?)
Ejemplo :
class Author(models.Model):
...
class Post(models.Model):
author = models.ForeignKey(Author)
Ahora elijo un ModelAdmin de modo que el autor aparezca en modo de lista:
class PostAdmin(admin.ModelAdmin):
list_display = [..., ''author'',...]
Ahora en el modo de lista, el campo de autor solo usará el método __unicode__
de la clase Author
para mostrar el autor. Además, me gustaría un enlace que apunte a la URL del autor correspondiente en el sitio de administración. ¿Es eso posible?
Método manual :
Para completar, agrego el método manual. Sería agregar 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
Eso funcionará para ese campo en particular, pero eso no es 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).
Estaba buscando una solución para el 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'')
Reemplaza ''parcial'' con ''curry'' de Django si no usa python> = 2.5.
No creo que haya un mecanismo para hacer lo que quieras de forma automática.
Pero en cuanto a determinar la ruta a una página de edición de administrador basada en la identificación de un objeto, todo lo que necesita son dos elementos de información:
a) self.model._meta.app_label
b) self.model._meta.module_name
Luego, por ejemplo, para ir a la página de edición de ese modelo, debería hacer lo siguiente:
''../%s_%s_change/%d'' % (self.model._meta.app_label, self.model._meta.module_name, item.id)
Eche un vistazo a django.contrib.admin.options.ModelAdmin.get_urls
para ver cómo lo hacen.
Supongo que podría tener un llamante que tenga un nombre de modelo y una identificación, cree un modelo del tipo especificado solo para obtener la etiqueta y el nombre (no es necesario que acceda a la base de datos) y genere la URL a anterior.
Pero, ¿estás seguro de que no puedes obtener usando inlines? Sería una mejor interfaz de usuario tener todos los componentes relacionados en una sola página ...
Editar:
Inlines (vinculadas a documentos) permiten que una interfaz de administrador muestre 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 represente 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.
Ver https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#admin-reverse-urls
Ejemplo:
from django.utils.html import format_html
def get_admin_change_link(app_label, model_name, obj_id, name):
url = reverse(''admin:%s_%s_change'' % (app_label, model_name),
args=(obj_id,))
return format_html(''<a href="%s">%s</a>'' % (
url, unicode(name)
))