我有一个名为Person
的模型,它与Book
具有外键关系,其中Book有许多字段,但我最关心的是author
(一个标准的CharField)。
话虽如此,在我的PersonAdmin
模型中,我想使用list_display
显示book.author
:
class PersonAdmin(admin.ModelAdmin):
list_display = ['book.author',]
我已经尝试了所有显而易见的方法,但似乎没有什么作用。
有什么建议吗?
我有一个名为Person
的模型,它与Book
具有外键关系,其中Book有许多字段,但我最关心的是author
(一个标准的CharField)。
话虽如此,在我的PersonAdmin
模型中,我想使用list_display
显示book.author
:
class PersonAdmin(admin.ModelAdmin):
list_display = ['book.author',]
我已经尝试了所有显而易见的方法,但似乎没有什么作用。
有什么建议吗?
作为另一个选项,您可以进行查找,例如:
#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
尽管上面有很多好的答案,但由于我对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模型链接此处
obj
是 BookAdmin
吗? - Kyiasget_author
函数将会减慢管理员中的list_display
速度,因为显示每个人都会进行一次SQL查询。PersonAdmin
中的get_queryset
方法,例如:def get_queryset(self, request):
return super(PersonAdmin,self).get_queryset(request).select_related('book')
之前:73个查询,用时36.02毫秒(其中67个查询在管理界面中重复)
之后:6个查询,用时10.81毫秒
__str__
方法,只需将外键添加到list_display
和list_select_related
中即可。 - Scratch'N'Purr像其他人一样,我也选择使用可调用对象。但是它们有一个缺点:默认情况下,您不能按照它们进行排序。幸运的是,这个问题有解决方案:
def author(self, obj):
return obj.book.author
author.admin_order_field = 'book__author'
def author(self):
return self.book.author
author.admin_order_field = 'book__author'
def author(self, obj):
。 - sheats在 Django 3.2 或更高版本中正确的做法是使用 display 装饰器
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
__unicode__
表示形式:
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#list-display
看起来它不支持在DB API的其他地方都使用的'book__author'
格式。
原来有一个这个特性的票证,但被标记为不会修复。我刚刚发布了一个代码片段,可以让admin.ModelAdmin支持'__'语法:
http://djangosnippets.org/snippets/2887/
这样你就可以做到:
class PersonAdmin(RelatedFieldAdmin):
list_display = ['book__author',]
这基本上只是在做其他答案中描述的同样的事情,但它会自动处理(1)设置admin_order_field (2)设置short_description和(3)修改查询集以避免为每一行进行数据库查询。
AttributeError: type object 'BaseModel' has no attribute '__metaclass__'
。 - Vincent van Leeuwen在PyPI上有一个非常易于使用的程序包可以确切地处理这个问题:django-related-admin。您也可以在GitHub上查看代码。
使用它,您想要实现的目标就像这样简单:
class PersonAdmin(RelatedFieldAdmin):
list_display = ['book__author',]
两个链接都包含安装和使用的完整细节,所以我不会在这里粘贴它们,以防它们改变。
另外一点需要注意的是,如果你已经在使用model.Admin
以外的其他东西(例如我之前在使用SimpleHistoryAdmin
),你可以这样做:class MyAdmin(SimpleHistoryAdmin, RelatedFieldAdmin)
。
通过使用可调用函数,您可以在列表显示中显示任何想要的内容。代码如下:
def book_author(object): return object.book.author class PersonAdmin(admin.ModelAdmin): list_display = [book_author,]
这个问题已经得到解决,但如果还有其他像我一样的“蠢蛋”没有立即从目前被接受的答案中理解,这里有更详细的说明。
ForeignKey
引用的模型类需要在其中拥有一个__unicode__
方法,就像这里:
class Category(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
这对我很有帮助,同样适用于上述情况。这适用于Django 1.0.2。
def __str__(self):
。 - Martlark
select_related
的作用。UserAdmin
的get_queryset()
必须被重写。” - interDist@admin.display(....)
。 - Eyong Kevin Enowanyo