Django admin:如何按没有数据库字段的自定义list_display字段之一进行排序
- 2025-03-18 08:54:00
- admin 原创
- 46
问题描述:
# 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 依赖底层数据库来执行排序?创建一个聚合字段来包含订单数量似乎有点过头了。
有趣的是:如果您在浏览器中手动更改 url 来对此列进行排序 - 它将会按预期工作!
解决方案 1:
我喜欢 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'
这样,您就只能在管理界面内进行注释。而不是对执行的每个查询都进行注释。
解决方案 2:
我还没有测试过这个(我很想知道它是否有效),但是如何定义一个自定义管理器,其中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'
编辑:我刚刚测试了这个想法并且它运行完美 - 不需要 django 管理员子类化!
解决方案 3:
我能想到的唯一方法是将字段非规范化。也就是说,创建一个真实的字段,该字段会进行更新以与其派生自的字段保持同步。我通常通过覆盖具有非规范化字段的模型或其派生自的模型上的保存来做到这一点:
# 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[...]
相关推荐
热门文章
项目管理软件有哪些?
热门标签
曾咪二维码
扫码咨询,免费领取项目管理大礼包!
云禅道AD