Django的pipe理员:如何通过一个没有数据库字段的自定义list_display字段进行sorting

# 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() 

我怎么能sorting客户,取决于他们有number_of_orders

admin_order_field属性不能在这里使用,因为它需要一个数据库字段进行sorting。 是否有可能,因为Django依赖底层数据库来执行sorting? 创build一个聚合字段来包含订单的数量看起来像在这里矫枉过正。

有趣的是:如果您在浏览器中手动更改url来对此列进行sorting,则会按预期工作!

我喜欢Greg对这个问题的解决scheme,但是我想指出,你可以直接在pipe理员那里做同样的事情:

 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' 

这样你只能在pipe理界面注释。 不是每个查询,你做。

我没有testing过(我有兴趣知道它是否有效),但是如何为Customer定义一个自定义pipe理器,其中包括汇总的订单数量,然后将admin_order_field设置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' 

编辑:我刚刚testing了这个想法,它的作品完美 – 没有djangopipe理子类需要!

我能想到的唯一方法是使领域非规范化。 那就是 – 创build一个真实的领域,得到更新,以保持与其派生的领域同步。 我通常通过覆盖保存在非规范化字段或模型的模型上来做到这一点:

 # models.py class Order(models.Model): bar = models.CharField[...] customer = models.ForeignKey(Customer) def save(self): super(Order, self).save() self.customer.number_of_orders = Order.objects.filter(customer=self.customer).count() self.customer.save() class Customer(models.Model): foo = models.CharField[...] number_of_orders = models.IntegerField[...]