我有一个Person
有一个外键关系模型Book
,其中有一些领域,但我最关心的是author
(标准CharField)。
有了这样说,在我的PersonAdmin
模式,我想显示book.author
使用list_display
:
class PersonAdmin(admin.ModelAdmin):
list_display = ['book.author',]
我已经尝试了所有的方法,显然这样做的,但似乎没有任何工作。
有什么建议?
我有一个Person
有一个外键关系模型Book
,其中有一些领域,但我最关心的是author
(标准CharField)。
有了这样说,在我的PersonAdmin
模式,我想显示book.author
使用list_display
:
class PersonAdmin(admin.ModelAdmin):
list_display = ['book.author',]
我已经尝试了所有的方法,显然这样做的,但似乎没有任何工作。
有什么建议?
作为另一种选择,你可以做一下UPS,如:
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所有伟大的答案,我仍然坚持。 下面是一个非常新手的角度来看我的解释。
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的模型链接点击这里
和其他人一样,我跟可调用也去了。 但是他们有一个缺点:在默认情况下,你不能对他们的命令。 幸运的是,对于一个解决方案:
def author(self):
return self.book.author
author.admin_order_field = 'book__author'
请注意,添加get_author
功能将放缓管理员的list_display,因为显示每个人会让一个SQL查询。
为了避免这种情况,您需要修改get_queryset
方法PersonAdmin,例如:
def get_queryset(self, request):
return super(PersonAdmin,self).get_queryset(request).select_related('book')
之前:在36.02ms 73个查询(在管理67个重复查询)
后:在10.81ms 6个查询
根据该文件,你只能显示__unicode__
一个ForeignKey的表示:
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#list-display
似乎奇怪的是它不支持'book__author'
这是用来在其他地方的DB API风格的格式。
原来有此功能的一票 ,因为不会修复被标记。
你可以告诉你在列表中显示想要的任何使用调用。 它是这样的:
def book_author(object): return 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。
如果你尝试以串联,你不会成功,除非:
在您的内联:
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
,不希望创建一个函数(和它的属性)为每一个,土而简单的解决办法是重写ModelAdmin
instace __getattr__
方法,动态创建的可调用:
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
属性,如book__author_verbose_name = 'Author name'
和category__is_new_boolean = True
。
可调用admin_order_field
属性被自动定义。
不要忘记使用list_select_related属性在你ModelAdmin
作出的Django避免aditional的查询。
有一个非常容易使用的PyPI提供包处理正是: Django的相关管理员 。 您还可以看到在GitHub上的代码 。
用这种方法,你想达到什么是简单:
class PersonAdmin(RelatedFieldAdmin):
list_display = ['book__author',]
这两个链接包含安装和使用的全部细节,所以我不会在这里他们在他们改变的情况下粘贴。
正如一个侧面说明,如果你已经使用了比其他东西model.Admin
(如我所用SimpleHistoryAdmin
代替),你可以这样做: class MyAdmin(SimpleHistoryAdmin, RelatedFieldAdmin)
AlexRobbins的回答为我工作,除了前两行需要在模型(也许这是假设?),并应参考自:
def book_author(self):
return self.book.author
然后管理部分工作得很好。
我喜欢这样的:
class CoolAdmin(admin.ModelAdmin):
list_display = ('pk', 'submodel__field')
@staticmethod
def submodel__field(obj):
return obj.submodel.field