Django admin:如何通过没有数据库字段的自定义list_display字段之一进行排序

mik*_*e_k 113 sorting django django-admin

# admin.py
class CustomerAdmin(admin.ModelAdmin):  
    list_display = ('foo', 'number_of_orders')

# models.py
class Order(models.Model):
    bar = models.CharField[...]
    customer = models.ForeignKey(Customer)

class Customer(models.Model):
    foo = models.CharField[...]
    def number_of_orders(self):
        return u'%s' % Order.objects.filter(customer=self).count()  
Run Code Online (Sandbox Code Playgroud)

我如何根据客户的不同对客户进行排序number_of_orders

admin_order_fieldproperty不能在这里使用,因为它需要一个数据库字段来进行排序.是否有可能,因为Django依赖底层数据库来执行排序?创建一个包含订单数量的聚合字段在这里看起来有点过分.

有趣的是:如果您在浏览器中手动更改URL以对此列进行排序 - 它按预期工作!

bbr*_*rik 149

我喜欢Greg解决这个问题的方法,但我想指出你可以直接在管理员中做同样的事情:

from django.db import models

class CustomerAdmin(admin.ModelAdmin):
    list_display = ('number_of_orders',)

    def get_queryset(self, request):
    # def queryset(self, request): # For Django <1.6
        qs = super(CustomerAdmin, self).get_queryset(request)
        # qs = super(CustomerAdmin, self).queryset(request) # For Django <1.6
        qs = qs.annotate(models.Count('order'))
        return qs

    def number_of_orders(self, obj):
        return obj.order__count
    number_of_orders.admin_order_field = 'order__count'
Run Code Online (Sandbox Code Playgroud)

这样您只需在管理界面内进行注释.不是您执行的每个查询.

  • 自定义list_display字段有两个参数:`self`和`obj`.`number_of_orders`应该是`def number_of_orders(self,obj):` (7认同)
  • 是的,这是一个更好的方法.:) (4认同)
  • 这个答案有[建议编辑](http://stackoverflow.com/suggested-edits/240451).我投票拒绝它,因为它删除了太多的文字.我不知道Django,我不知道提议的代码更改是否值得一提. (2认同)
  • 应该是get_queryset(self,request):...对于Django 1.6+ (2认同)

Gre*_*reg 49

我没有测试过这个(我有兴趣知道它是否有效)但是如何定义一个自定义管理器,Customer其中包括聚合的订单数量,然后设置admin_order_field为该聚合,即

from django.db import models 


class CustomerManager(models.Manager):
    def get_query_set(self):
        return super(CustomerManager, self).get_query_set().annotate(models.Count('order'))

class Customer(models.Model):
    foo = models.CharField[...]

    objects = CustomerManager()

    def number_of_orders(self):
        return u'%s' % Order.objects.filter(customer=self).count()
    number_of_orders.admin_order_field = 'order__count'
Run Code Online (Sandbox Code Playgroud)

编辑:我刚刚测试了这个想法,它的工作完美 - 没有django管理子类需要!