Clés étrangères en django
si un modèle django contient un champ Clé étranger, et si ce champ est affiché en mode liste, alors il apparaît comme texte, au lieu d'afficher un lien au corps étranger.
est-il possible d'afficher automatiquement toutes les clés étrangères sous forme de liens plutôt que de texte plat?
(bien sûr, il est possible de le faire sur un champ par champ, mais est-il un général méthode?)
Exemple:
class Author(models.Model):
...
class Post(models.Model):
author = models.ForeignKey(Author)
maintenant je choisis un ModelAdmin tel que l'auteur apparaît en mode liste:
class PostAdmin(admin.ModelAdmin):
list_display = [..., 'author',...]
Maintenant en mode liste, le champ auteur utilisera simplement le __unicode__
méthode de l' Author
classe pour afficher l'auteur. Sur le dessus de cela, je voudrais un lien pointant vers l'url de l'auteur correspondant dans l'admin du site. Est-ce possible?
Manuel méthode:
par souci d'exhaustivité, j'ajoute la méthode manuelle. Il serait d'ajouter une méthode author_link
dans le PostAdmin
catégorie:
def author_link(self, item):
return '<a href="../some/path/%d">%s</a>' % (item.id, unicode(item))
author_link.allow_tags = True
Qui va travailler pour ce domaine particulier, mais qui est ce que je veux. Je veux une méthode générale pour obtenir le même effet. (Un des problèmes est de savoir comment trouver automatiquement le chemin d'accès à un objet sur le site admin de django.)
3 réponses
je ne pense pas qu'il existe un mécanisme pour faire ce que vous voulez automatiquement hors de la boîte.
mais en ce qui concerne la détermination du chemin vers une page d'édition admin basée sur l'id d'un objet, tout ce dont vous avez besoin sont deux informations:
a)self.model._meta.app_label
b)self.model._meta.module_name
ensuite, par exemple, pour aller à la page d'édition de ce modèle vous feriez:
'../%s_%s_change/%d' % (self.model._meta.app_label, self.model._meta.module_name, item.id)
regardez django.contrib.admin.options.ModelAdmin.get_urls
pour voir comment ils le font.
je suppose que vous pourrait avoir un callable qui prend un nom de modèle et un id, crée un modèle du type spécifié juste pour obtenir l'étiquette et le nom (pas besoin de frapper la base de données) et génère L'URL a ci-dessus.
mais Êtes-vous sûr que vous ne pouvez pas obtenir en utilisant inlines? Cela permettrait à une meilleure interface utilisateur d'avoir tous les composants connexes dans une page...
Edit:
Inlines (lié à docs) permet à une interface d'administration d'afficher un parent-enfant relation en une page au lieu de la diviser en deux.
dans l'exemple Post / Author que vous avez fourni, l'utilisation d'inlines signifierait que la page pour éditer des articles afficherait également un formulaire en ligne pour ajouter/éditer/supprimer des auteurs. Beaucoup plus naturel pour l'utilisateur final.
ce que vous pouvez faire dans la vue Liste administrateur est de créer un callable dans le modèle Post qui rendra une liste d'auteurs séparée par des virgules. Donc, vous aurez votre liste de diffusion montrant les auteurs appropriés, et vous modifiez les auteurs associés à un Post directement dans L'interface d'administration du Post.
je cherchais une solution au même problème et je suis tombé sur cette question... fini par le résoudre moi-même. L'OP n'est peut-être plus intéressée, mais cela pourrait quand même être utile à quelqu'un.
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')
remplacer 'partial' par 'curry' de Django si vous n'utilisez pas python >= 2.5.
voir https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#admin-reverse-urls
Exemple:
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)
))