fields Django的管理員:如何通過一個沒有數據庫字段的自定義list_display字段進行排序




django admin search fields (3)

# 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依賴底層數據庫來執行排序? 創建一個包含訂單數量的聚合字段似乎在這裡是一種矯枉過正的行為。

有趣的是:如果您在瀏覽器中手動更改網址來排序此列 - 它會按預期工作!


我能想到的唯一方法是使該領域非規範化。 那是 - 創建一個真正的領域,得到更新,以保持與它來自的領域同步。 我通常通過覆蓋保存在模型上的非規範化字段或模型來實現此目的:

# 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[...]

我喜歡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設置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管理子類的要求!





django-admin