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 
作为这里的主旨
 像boolean和short_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