我有一个Person模型,它与Book有外键关系,Book有许多字段,但我最关心的是author(一个标准CharField)。

话虽如此,在我的PersonAdmin模型中,我想显示book。作者使用list_display:

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

我已经尝试了所有显而易见的方法,但似乎都不起作用。

有什么建议吗?


当前回答

你可以使用可调用对象在列表显示中显示你想要的任何东西。它看起来是这样的:


def book_author(object):
  return object.book.author

class PersonAdmin(admin.ModelAdmin):
  list_display = [book_author,]

其他回答

根据文档,你只能显示ForeignKey的__unicode__表示:

http://docs.djangoproject.com/en/dev/ref/contrib/admin/#list-display

似乎奇怪的是,它不支持'book__author'风格的格式,这种格式在DB API中随处可见。

事实证明,这个功能有一个门票,它被标记为不会修复。

作为另一种选择,你可以像这样查找:

#models.py
class UserAdmin(admin.ModelAdmin):
    list_display = (..., 'get_author')
    
    def get_author(self, obj):
        return obj.book.author
    get_author.short_description = 'Author'
    get_author.admin_order_field = 'book__author'

从Django 3.2开始,你可以使用display()装饰器:

#models.py
class UserAdmin(admin.ModelAdmin):
    list_display = (..., 'get_author')
    
    @admin.display(ordering='book__author', description='Author')
    def get_author(self, obj):
        return obj.book.author

这个答案已经被接受了,但如果还有其他傻瓜(比如我)没有立即从目前接受的答案中得到它,这里有更多的细节。

ForeignKey引用的模型类需要有一个__unicode__方法,如下所示:

class Category(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

这对我来说很重要,也适用于上述情况。这适用于Django 1.0.2。

我可能会迟到,但这是另一种方法。你可以简单地在你的模型中定义一个方法,并通过list_display访问它,如下所示:

models.py

class Person(models.Model):
    book = models.ForeignKey(Book, on_delete=models.CASCADE)

    def get_book_author(self):
        return self.book.author

admin.py

class PersonAdmin(admin.ModelAdmin):
    list_display = ('get_book_author',)

但是这种方法和上面提到的其他方法会在列表视图页面的每一行中增加两个额外的查询。为了优化这一点,我们可以覆盖get_queryset来注释所需的字段,然后在ModelAdmin方法中使用注释的字段

admin.py

from django.db.models.expressions import F

@admin.register(models.Person)
class PersonAdmin(admin.ModelAdmin):
    list_display = ('get_author',)
    def get_queryset(self, request):
        queryset = super().get_queryset(request)
        queryset = queryset.annotate(
            _author = F('book__author')
        )
        return queryset

    @admin.display(ordering='_author', description='Author')
    def get_author(self, obj):
        return obj._author

尽管上面有很多很棒的答案,但由于我是Django的新手,我仍然被困住了。以下是我从新手的角度给出的解释。

models.py

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

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

admin.py(不正确的方式)-你认为它可以通过使用'model__field'引用来工作,但事实并非如此

class BookAdmin(admin.ModelAdmin):
    model = Book
    list_display = ['title', 'author__name', ]

admin.site.register(Book, BookAdmin)

admin.py(正确的方式)——这是你在Django中引用外键名的方式

class BookAdmin(admin.ModelAdmin):
    model = Book
    list_display = ['title', 'get_name', ]

    def get_name(self, obj):
        return obj.author.name
    get_name.admin_order_field  = 'author'  #Allows column order sorting
    get_name.short_description = 'Author Name'  #Renames column head

    #Filtering on side - for some reason, this works
    #list_filter = ['title', 'author__name']

admin.site.register(Book, BookAdmin)

如需更多参考,请参阅Django模型链接