1. ホーム
  2. django

[解決済み] Django admin: データベースフィールドを持たないカスタム list_display フィールドの1つでソートする方法

2022-06-12 02:49:19

質問

# 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'

この方法では、管理画面の中だけにアノテーションを付けることになります。すべてのクエリでアノテーションするわけではありません。