问题:Django ModelAdmin中的“ list_display”可以显示ForeignKey字段的属性吗?
我有一个Person模型,它与有一个外键关系Book,该模型有许多字段,但我最关心的是author(标准CharField)。
话虽如此,在我的PersonAdmin模型中,我想book.author使用显示list_display:
class PersonAdmin(admin.ModelAdmin):
    list_display = ['book.author',]
我已经尝试了所有显而易见的方法来执行此操作,但是似乎没有任何效果。
有什么建议么?
 
        
        
            
            
            
                
                    
                    
I have a Person model that has a foreign key relationship to Book, which has a number of fields, but I’m most concerned about author (a standard CharField).
With that being said, in my PersonAdmin model, I’d like to display book.author using list_display:
class PersonAdmin(admin.ModelAdmin):
    list_display = ['book.author',]
I’ve tried all of the obvious methods for doing so, but nothing seems to work.
Any suggestions?
     
                 
             
            
         
        
        
回答 0
作为另一种选择,您可以进行如下查找:
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'
 
        
        
            
            
            
                
                    
As another option, you can do look ups like:
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
尽管上面有很多很棒的答案,但由于我是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模型链接
 
        
        
            
            
            
                
                    
Despite all the great answers above and due to me being new to Django, I was still stuck.  Here’s my explanation from a very newbie perspective.
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 (Incorrect Way) – you think it would work by using ‘model__field’ to reference, but it doesn’t
class BookAdmin(admin.ModelAdmin):
    model = Book
    list_display = ['title', 'author__name', ]
admin.site.register(Book, BookAdmin)
admin.py (Correct Way)  – this is how you reference a foreign key name the Django way
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)
For additional reference, see the Django model link here
     
                 
             
            
         
        
        
回答 2
和其余的一样,我也使用可调用对象。但是它们有一个缺点:默认情况下,您无法订购它们。幸运的是,有一个解决方案:
的Django> = 1.8
def author(self, obj):
    return obj.book.author
author.admin_order_field  = 'book__author'
Django <1.8
def author(self):
    return self.book.author
author.admin_order_field  = 'book__author'
 
        
        
            
            
            
                
                    
Like the rest, I went with callables too. But they have one downside: by default, you can’t order on them. Fortunately, there is a solution for that:
Django >= 1.8
def author(self, obj):
    return obj.book.author
author.admin_order_field  = 'book__author'
Django < 1.8
def author(self):
    return self.book.author
author.admin_order_field  = 'book__author'
     
                 
             
            
         
        
        
回答 3
请注意,添加该get_author功能会减慢admin中的list_display速度,因为显示每个人都会进行SQL查询。
为了避免这种情况,您需要get_queryset在PersonAdmin中修改方法,例如:
def get_queryset(self, request):
    return super(PersonAdmin,self).get_queryset(request).select_related('book')
之前:36.02毫秒内有73个查询(管理员中有67个重复查询)
之后:10.81毫秒内进行6次查询
 
        
        
            
            
            
                
                    
Please note that adding the get_author function would slow the list_display in the admin, because showing each person would make a SQL query.
To avoid this, you need to modify get_queryset method in PersonAdmin, for example:
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
     
                 
             
            
         
        
        
回答 4
        
        
        
        
回答 5
我刚刚发布了一个片段,使admin.ModelAdmin支持’__’语法:
http://djangosnippets.org/snippets/2887/
因此,您可以执行以下操作:
class PersonAdmin(RelatedFieldAdmin):
    list_display = ['book__author',]
基本上,这只是在做其他答案中描述的相同操作,但是它会自动处理(1)设置admin_order_field(2)设置short_description以及(3)修改查询集以避免每一行都有数据库命中。
 
        
        
            
            
            
                
                    
I just posted a snippet that makes admin.ModelAdmin support ‘__’ syntax:
http://djangosnippets.org/snippets/2887/
So you can do:
class PersonAdmin(RelatedFieldAdmin):
    list_display = ['book__author',]
This is basically just doing the same thing described in the other answers, but it automatically takes care of (1) setting admin_order_field (2) setting short_description and (3) modifying the queryset to avoid a database hit for each row.
     
                 
             
            
         
        
        
回答 6
您可以使用可调用对象在列表显示中显示所需的任何内容。它看起来像这样:
def book_author(object):
  返回object.book.author
类PersonAdmin(admin.ModelAdmin):
  list_display = [book_author,]
 
        
        
            
            
            
                
                    
You can show whatever you want in list display by using a callable. It would look like this:
def book_author(object):
  return object.book.author
class PersonAdmin(admin.ModelAdmin):
  list_display = [book_author,]
     
                 
             
            
         
        
        
回答 7
这个已经被接受了,但是如果还有其他假人(像我一样)没有立即从当前接受的答案中得到答案,那么这里有更多细节。
ForeignKey需要引用的模型类在其中需要一个__unicode__方法,例如:
class Category(models.Model):
    name = models.CharField(max_length=50)
    def __unicode__(self):
        return self.name
这对我来说很重要,应该适用于上述情况。这适用于Django 1.0.2。
 
        
        
            
            
            
                
                    
This one’s already accepted, but if there are any other dummies out there (like me) that didn’t immediately get it from the presently accepted answer, here’s a bit more detail. 
The model class referenced by the ForeignKey needs to have a __unicode__ method within it, like here: 
class Category(models.Model):
    name = models.CharField(max_length=50)
    def __unicode__(self):
        return self.name
That made the difference for me, and should apply to the above scenario.  This works on Django 1.0.2.
     
                 
             
            
         
        
        
回答 8
如果您有很多关联属性字段供使用,list_display并且不想为每个函数创建一个函数(及其属性),那么一个肮脏而简单的解决方案将覆盖ModelAdmininstace __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。
callable admin_order_field属性是自动定义的。
不要忘记在您的列表中使用list_select_related属性,ModelAdmin以使Django避免常规查询。
 
        
        
            
            
            
                
                    
If you have a lot of relation attribute fields to use in list_display and do not want create a function (and it’s attributes) for each one, a dirt but simple solution would be override the ModelAdmin instace __getattr__ method, creating the callables on the fly:
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
As gist here
Callable especial attributes like boolean and short_description must be defined as ModelAdmin attributes, eg book__author_verbose_name = 'Author name' and category__is_new_boolean = True.
The callable admin_order_field attribute is defined automatically.
Don’t forget to use the list_select_related attribute in your ModelAdmin to make Django avoid aditional queries.
     
                 
             
            
         
        
        
回答 9
PyPI中有一个非常易于使用的软件包,可以准确地处理该软件包:django-related-admin。您还可以在GitHub中查看代码。
使用此功能,您想要实现的过程很简单:
class PersonAdmin(RelatedFieldAdmin):
    list_display = ['book__author',]
这两个链接均包含安装和使用的完整详细信息,因此,如果它们发生更改,我就不会在此处粘贴它们。
顺便提一句,如果您已经使用了其他工具model.Admin(例如,我正在使用SimpleHistoryAdmin),则可以执行以下操作:class MyAdmin(SimpleHistoryAdmin, RelatedFieldAdmin)。
 
        
        
            
            
            
                
                    
There is a very easy to use package available in PyPI that handles exactly that: django-related-admin. You can also see the code in GitHub.
Using this, what you want to achieve is as simple as:
class PersonAdmin(RelatedFieldAdmin):
    list_display = ['book__author',]
Both links contain full details of installation and usage so I won’t paste them here in case they change.
Just as a side note, if you’re already using something other than model.Admin (e.g. I was using SimpleHistoryAdmin instead), you can do this: class MyAdmin(SimpleHistoryAdmin, RelatedFieldAdmin).
     
                 
             
            
         
        
        
回答 10
如果您在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
 
        
        
            
            
            
                
                    
if you try it in Inline, you wont succeed unless:
in your inline:
class AddInline(admin.TabularInline):
    readonly_fields = ['localname',]
    model = MyModel
    fields = ('localname',)
in your model (MyModel):
class MyModel(models.Model):
    localization = models.ForeignKey(Localizations)
    def localname(self):
        return self.localization.name
     
                 
             
            
         
        
        
回答 11
AlexRobbins的答案对我有用,除了前两行需要在模型中(也许这是假设的?),并且应该引用self:
def book_author(self):
  return self.book.author
然后管理部分可以很好地工作。
 
        
        
            
            
            
                
                    
AlexRobbins’ answer worked for me, except that the first two lines need to be in the model (perhaps this was assumed?), and should reference self:
def book_author(self):
  return self.book.author
Then the admin part works nicely.
     
                 
             
            
         
        
        
回答 12
我更喜欢这样:
class CoolAdmin(admin.ModelAdmin):
    list_display = ('pk', 'submodel__field')
    @staticmethod
    def submodel__field(obj):
        return obj.submodel.field
 
        
        
            
            
            
                
                    
I prefer this:
class CoolAdmin(admin.ModelAdmin):
    list_display = ('pk', 'submodel__field')
    @staticmethod
    def submodel__field(obj):
        return obj.submodel.field
     
                 
             
            
         
        
        
	
	声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。