Django ModelAdmin中的“list_display”可以显示ForeignKey字段的属性吗?

我有一个与Book有外键关系的Person模型。 书有很多字段,但是我最关心的是“作者”(一个标准的CharField)。

据说,在我的PersonAdmin模型中,我想使用“list_display”显示“book.author”。 我已经尝试了所有明显的方法(见下文),但似乎没有任何工作。 有什么build议么?

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

作为另一种select,你可以看起来像:

 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' 

尽pipe上面有很多好的答案,并且由于我是Django的新手,但我还是陷入了困境。 这是我从一个非常新的angular度的解释。

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模型链接

和其余的一样,我也带着可卡因。 但他们有一个缺点:默认情况下,你不能在他们的订单。 幸运的是,有一个解决scheme:

 def author(self): return self.book.author author.admin_order_field = 'book__author' 

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

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

奇怪的是,它不支持在DB API中使用的'book__author'风格的格式。

原来有这个function的票证 ,标记为不会修复。

请注意,添加get_author函数会减慢pipe理中的list_display,因为显示每个人都会进行SQL查询。

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

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

之前:在36.02ms内查询73次(在pipe理员中重复查询67次)

之后:10.81ms内的6个查询

您可以通过使用可调用的函数来显示列表显示中的任何内容。 它看起来像这样:


 def book_author(object):
  返回object.book.author

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

我刚刚发布了一个使admin.ModelAdmin支持'__'语法的代码片段:

http://djangosnippets.org/snippets/2887/

所以你可以这样做:

 class PersonAdmin(RelatedFieldAdmin): list_display = ['book__author',] 

这基本上只是做与其他答案中描述的相同的事情,但它会自动处理(1)设置admin_order_field(2)设置short_description和(3)修改查询集,以避免每行的数据库命中。

这个已经被接受了,但是如果还有其他的傻子(像我一样)没有立即从目前接受的答案中得到它,这里有一些细节。

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

 class Category(models.Model): name = models.CharField(max_length=50) def __unicode__(self): return self.name 

这对我有所帮助,应该适用于上述情况。 这适用于Django 1.0.2。

PyPI中有一个非常易于使用的软件包,可以完全处理: django-related-admin 。 你也可以在GitHub中看到代码 。

使用这个,你想要达到的是如此简单:

 class PersonAdmin(RelatedFieldAdmin): list_display = ['book__author',] 

这两个链接都包含完整的安装和使用的细节,所以我不会在这里粘贴他们的情况下,他们改变。

正如一个侧面说明,如果你已经使用的东西比model.Admin (例如我使用SimpleHistoryAdmin代替),你可以这样做: class MyAdmin(SimpleHistoryAdmin, RelatedFieldAdmin)

如果你在Inline中尝试它,除非:

在你的内联:

 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 

如果在list_display使用了很多关系属性字段,并且不想为每个属性创build一个函数(以及它的属性),那么一个简单而又简单的解决scheme将会覆盖ModelAdmin实例__getattr__方法,从而快速创build可调用对象:

 class DynamicLookupMixin(object): ''' a mixin to add dynamic callable attributes like 'book__author' which return a function that return the instance.book.author value ''' def __getattr__(self, attr): if ('__' in attr and not attr.startswith('_') and not attr.endswith('_boolean') and not attr.endswith('_short_description')): def dyn_lookup(instance): # traverse all __ lookups return reduce(lambda parent, child: getattr(parent, child), attr.split('__'), instance) # get admin_order_field, boolean and short_description dyn_lookup.admin_order_field = attr dyn_lookup.boolean = getattr(self, '{}_boolean'.format(attr), False) dyn_lookup.short_description = getattr( self, '{}_short_description'.format(attr), attr.replace('_', ' ').capitalize()) return dyn_lookup # not dynamic lookup, default behaviour return self.__getattribute__(attr) # use examples @admin.register(models.Person) class PersonAdmin(admin.ModelAdmin, DynamicLookupMixin): list_display = ['book__author', 'book__publisher__name', 'book__publisher__country'] # custom short description book__publisher__country_short_description = 'Publisher Country' @admin.register(models.Product) class ProductAdmin(admin.ModelAdmin, DynamicLookupMixin): list_display = ('name', 'category__is_new') # to show as boolean field category__is_new_boolean = True 

作为这里的主旨

booleanshort_description这样可调用的ModelAdmin属性必须被定义为ModelAdmin属性,例如book__author_verbose_name = 'Author name'category__is_new_boolean = True

可调用的admin_order_field属性是自动定义的。

不要忘记在你的ModelAdmin使用list_select_related属性来使Django避免附加查询。

AlexRobbins的答案对我很有帮助,只是前两行需要在模型中(也许这是假定的),并且应该引用self:

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

然后pipe理部分很好地工作。

我更喜欢这个:

 class CoolAdmin(admin.ModelAdmin): list_display = ('pk', 'submodel__field') @staticmethod def submodel__field(obj): return obj.submodel.field