# 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は基礎となるDBに基づいてソートを実行しますか?注文数を含む集約フィールドを作成することは、ここではやり過ぎのようです。
おもしろいことに、ブラウザでURLを手動で変更してこの列をソートすると、期待どおりに機能します!
私はこの問題に対する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'
この方法では、管理インターフェース内でのみ注釈を付けます。すべてのクエリを実行するわけではありません。
私はこれをテストしていません(うまくいくかどうか知りたいです)が、集約された注文数を含む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=管理サブクラス化が必要です!
私が考えることができる唯一の方法は、フィールドを非正規化することです。つまり、更新元のフィールドと同期を保つために更新される実際のフィールドを作成します。私は通常、非正規化されたフィールドまたはモデルの派生元のモデルでsaveをオーバーライドすることでこれを行います。
# 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[...]