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

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

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

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

有什么建议吗?


当前回答

AlexRobbins的回答对我来说很有用,除了前两行需要在模型中(也许这是假设的?),并且应该引用self:

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

然后管理部分工作得很好。

其他回答

如果你尝试在内联,你不会成功,除非:

在内联中:

class AddInline(admin.TabularInline):
    readonly_fields = ['localname',]
    model = MyModel
    fields = ('localname',)

在你的模型(MyModel):

class MyModel(models.Model):
    localization = models.ForeignKey(Localizations)

    def localname(self):
        return self.localization.name

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

#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

请注意,添加get_author函数会减慢管理中的list_display,因为显示每个人会产生SQL查询。

为了避免这种情况,您需要修改PersonAdmin中的get_queryset方法,例如:

def get_queryset(self, request):
    return super(PersonAdmin,self).get_queryset(request).select_related('book')

之前:36.02ms内73个查询(管理中67个重复查询) 之后:10.81ms内查询6次

对于Django >= 3.2

在Django 3.2或更高版本中,正确的方法是使用显示装饰器

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

    @admin.display(description='Author Name', ordering='author__name')
    def get_author_name(self, obj):
        return obj.author.name

尽管上面有很多很棒的答案,但由于我是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模型链接