# 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()
我如何根据客户的number_of_orders
对客户进行排序?
admin_order_field
属性,因为它需要对数据库字段进行排序。是否有可能,因为Django依赖底层数据库来执行排序?创建一个包含订单数量的聚合字段在这里看起来有点过分。
有趣的是:如果您在浏览器中手动更改网址以对此列进行排序 - 它会按预期工作!
答案 0 :(得分:142)
我喜欢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'
这样您只需在管理界面内注释。不是每个查询都这样做。
答案 1 :(得分:46)
我没有对此进行测试(我有兴趣知道它是否有效)但是如何为Customer
定义一个自定义管理器,其中包括聚合的订单数量,然后设置{{1}到那个聚合,即
admin_order_field
编辑:我刚刚测试了这个想法并且它完美运行 - 不需要django admin子类化!
答案 2 :(得分:0)
我能想到的唯一方法是对场进行非规范化。也就是说 - 创建一个真实的字段,使其更新以与其派生的字段保持同步。我通常通过覆盖使用非规范化字段或其派生的模型来保存模型来执行此操作:
# 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[...]