Как я могу перечислить все объекты, связанные с внешними ключами, в админ-панели Django?

Я хотел бы реализовать очень простую функцию с административной панелью django, но я не смог найти правильный путь для достижения этой цели:

model.py

class Author(models.Model):
    name = models.CharField()

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

admin.py

class AuthorAdmin(admin.ModelAdmin):
    pass
admin.site.register(Author, AuthorAdmin)

Как я могу добавить гиперссылку на каждый элемент (Автор) в обзоре списка авторов, который ссылается на представление, показывающее все книги определенного автора? Например:

  • Джоан Роулинг (книги)
  • Дж.Р.Р. Толкин (книги)

где книги - гиперссылка на сайт, на котором показаны все книги автора.

3 ответа

Решение

Вы ищете ModelAdmin.list_filter.

Установите list_filter, чтобы активировать фильтры в правой боковой панели страницы списка изменений администратора. Listfilter может быть именем поля, где указанное поле должно быть BooleanField, CharField, DateField, DateTimeField, IntegerField, ForeignKey или ManyToManyField, например:

 # Add a list filter author to BookAdmin.
 # Now you can filter books by author.
 class BookAdmin(ModelAdmin):
    list_filter = ('author', )

Теперь вы можете использовать предложение @Wolph для добавления ссылки в список автора_дисплея. Эта ссылка указывает на список книг, отфильтрованный по автору:

# Add hyperlinks to AuthorAdmin.
# Now you can jump to the book list filtered by autor. 
class AuthorAdmin(admin.ModelAdmin):
    def authors(self):
        return '<a href="/admin/appname/book/?author__id__exact=%d">%s</a>' % (self.author_id, self.author)
    authors.allow_tags = True

АЛЬТЕРНАТИВА. Чтобы сохранить клик, вы также можете указать на вид изменения книги напрямую:

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

def get_admin_url(self):
    return "/admin/appname/books/%d/" %self.id


class BookAdmin(admin.ModelAdmin):
    def authors(self):
        html = ""
        for obj in Books.objects.filter(author__id_exact=self.id):
            html += '<p><a href="%s">%s</a></p>' %(obj.get_admin_url(), obj.title)
        return html
    authors.allow_tags = True

    list_display = ['title', authors]

Отказ от ответственности: не проверено, но если вы исправите опечатку, это сработает!:)

Обратите внимание, что эти ссылки также могут быть введены в других точках администратора. Когда вы добавляете его в виджет, вы можете перейти от изменения вида к изменению вида.

Изучите реализацию объекта InlineModelAdmin.

# admin.py
class BooksInline(admin.TabularInline):
    model = Books

class AuthorAdmin(admin.ModelAdmin):
    inlines = [BooksInline]

Отредактированный ответ в ответ на комментарий ОП:

class AuthorAdmin(admin.ModelAdmin):
    list_display = ['name', 'books_published']

    def books_published(self, obj):
        redirect_url = reverse('admin:books_changelist')
        extra = "?author__id__exact=%d" % (obj.id)
        return "<a href='%s'>Books by author</a>" % (redirect_url + extra)

    books_published.allow_tags = True

На самом деле это не так просто, как вы думаете, возможно, но не тривиально, так как документации по этой функции не так много:)

Вам нужен пользовательский столбец, который генерируется функцией, которая дает вам ссылку на администратора Django с заданным фильтром. Что-то вроде этого (из головы так не проверено) должно сделать свое дело:

class AuthorAdmin(admin.ModelAdmin):
    def authors(self):
        return '<a href="?author=%d">%s</a>' % (self.author_id, self.author)
    authors.allow_html = True

    list_display = ['title', authors]
Другие вопросы по тегам