Can “list_display” in a Django ModelAdmin display attributes of ForeignKey fields?
我有一个
尽管如此,在我的
1 2 | class PersonAdmin(admin.ModelAdmin): list_display = ['book.author',] |
我已经尝试过所有显而易见的方法,但似乎没有任何效果。
有什么建议吗?
作为另一种选择,您可以进行如下查找:
1 2 3 4 5 6 7 | 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' |
尽管上面所有的答案都很好,而且由于我是刚到姜哥的人,我还是被困住了。这是我从一个新手的角度来解释的。
模特儿
1 2 3 4 5 6 | 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_uu field"来引用,但它不能
1 2 3 4 5 | class BookAdmin(admin.ModelAdmin): model = Book list_display = ['title', 'author__name', ] admin.site.register(Book, BookAdmin) |
admin.py(正确的方式)-这是如何引用外键名django方式
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 model链接
和其他人一样,我也带着可卡因去了。但它们有一个缺点:默认情况下,您不能订购它们。幸运的是,有一个解决方案:
1 2 3 | def author(self): return self.book.author author.admin_order_field = 'book__author' |
请注意,添加
为了避免这种情况,您需要在Personadmin中修改
1 2 | def get_queryset(self, request): return super(PersonAdmin,self).get_queryset(request).select_related('book') |
Before: 73 queries in 36.02ms (67 duplicated queries in admin)
After: 6 queries in 10.81ms
根据文档,您只能显示foreignkey的
http://docs.djangoproject.com/en/dev/ref/contrib/admin/列表显示
奇怪的是,它不支持DBAPI中其他地方使用的
结果发现有一张关于此功能的罚单,标记为"无法修复"。
我刚刚发布了一个代码片段,它使admin.modeladmin支持"uuuuu"语法:
http://djangosnippets.org/snippets/2887/
所以你可以这样做:
1 2 | class PersonAdmin(RelatedFieldAdmin): list_display = ['book__author',] |
这基本上是在做其他答案中描述的相同的事情,但它自动处理(1)设置管理顺序字段(2)设置简短描述和(3)修改查询集以避免每行的数据库命中。
您可以使用Callable在列表显示中显示您想要的任何内容。如下所示:
1 2 3 4 5 | def book_author(object): return object.book.author class PersonAdmin(admin.ModelAdmin): list_display = [book_author,] |
这一个已经被接受了,但是如果有其他的傻瓜(像我一样)没有立即从目前接受的答案中得到答案,这里有更多的细节。
1 2 3 4 5 | class Category(models.Model): name = models.CharField(max_length=50) def __unicode__(self): return self.name |
这对我来说是不同的,应该适用于上面的场景。这在Django 1.0.2上工作。
如果您在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 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 |
这里是要点
可调用的特殊属性,如
可调用的
不要忘记使用
如果您在内联中进行尝试,则不会成功,除非:
在你的内联:
1 2 3 4 | class AddInline(admin.TabularInline): readonly_fields = ['localname',] model = MyModel fields = ('localname',) |
在您的模型(MyModel)中:
1 2 3 4 5 | class MyModel(models.Model): localization = models.ForeignKey(Localizations) def localname(self): return self.localization.name |
Pypi中有一个非常容易使用的包,它可以精确地处理这个问题:django相关的管理。您还可以在GitHub中看到代码。
使用此功能,您想要实现的简单方法如下:
1 2 | class PersonAdmin(RelatedFieldAdmin): list_display = ['book__author',] |
这两个链接都包含安装和使用的完整详细信息,因此我不会将它们粘贴到此处以防更改。
作为旁注,如果你已经在使用除
亚历克斯罗宾斯的回答对我很有效,只是前两行需要在模型中(也许这是假设的?),并应参考自身:
1 2 | def book_author(self): return self.book.author |
然后管理部分工作得很好。
我更喜欢这个:
1 2 3 4 5 6 | class CoolAdmin(admin.ModelAdmin): list_display = ('pk', 'submodel__field') @staticmethod def submodel__field(obj): return obj.submodel.field |