Внешние ключи в отображении списка администратора django - PullRequest
37 голосов
/ 18 марта 2010

Если модель django содержит поле внешнего ключа, и если это поле отображается в режиме списка, оно отображается как текст вместо отображения ссылки на внешний объект.

Можно ли автоматически отображать все внешние ключи в виде ссылок вместо простого текста?

(конечно, это можно сделать на основе полей, но есть ли общий метод?)

Пример :

class Author(models.Model):
    ...

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

Теперь я выбираю ModelAdmin таким образом, чтобы автор появлялся в режиме списка:

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

Теперь в режиме списка поле автора будет просто использовать метод __unicode__ класса Author для отображения автора. В довершение всего я хотел бы ссылку , указывающую на URL соответствующего автора на сайте администратора. Это возможно?

Ручной метод :

Ради полноты добавлю ручной метод. Было бы добавить метод author_link в класс PostAdmin:

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

Это будет работать для этого конкретного поля, но это не , что я хочу. Я хочу общий метод для достижения того же эффекта. (Одна из проблем заключается в том, как автоматически определить путь к объекту на сайте администратора django.)

Ответы [ 3 ]

18 голосов
/ 01 июля 2010

Я искал решение той же проблемы и наткнулся на этот вопрос ... в итоге решил сам. ОП может больше не интересоваться, но это все равно может быть кому-то полезно.

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

Замените «частичное» на «карри» Джанго, если не используете python> = 2.5.

9 голосов
/ 18 марта 2010

Я не думаю, что есть механизм, который автоматически делает то, что вы хотите, из коробки.

Но для определения пути к странице редактирования администратора, основанной на идентификаторе объекта, все, что вам нужно, это две части информации:

а) self.model._meta.app_label

б) self.model._meta.module_name

Затем, например, чтобы перейти на страницу редактирования для этой модели, вы должны сделать:

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

Взгляните на django.contrib.admin.options.ModelAdmin.get_urls, чтобы увидеть, как они это делают.

Полагаю, у вас может быть вызываемый объект, который принимает имя модели и идентификатор, создает модель указанного типа просто для получения метки и имени (не нужно обращаться к базе данных) и генерирует URL-адрес выше.

Но вы уверены, что не можете использовать встроенные функции? Для лучшего пользовательского интерфейса было бы лучше иметь все связанные компоненты на одной странице ...

Редактировать:

Inlines (связанный с документами) позволяет интерфейсу администратора отображать родительские и дочерние отношения на одной странице, а не разбивать их на две.

В приведенном вами примере сообщения / автора использование встроенных символов будет означать, что на странице редактирования сообщений будет также отображаться встроенная форма для добавления / редактирования / удаления авторов. Гораздо более естественным для конечного пользователя.

В представлении списка администраторов вы можете создать вызываемый элемент в модели Post, который будет отображать список авторов через запятую. Таким образом, у вас будет представление списка сообщений с указанием соответствующих авторов, и вы редактируете авторов, связанных с сообщением, непосредственно в интерфейсе администратора сообщений.

3 голосов
/ 20 мая 2014

См. https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#admin-reverse-urls

Пример:

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