# 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 вручную в браузере к виду на этом столбце - он работает как ожидалось!
Единственный способ, который я могу придумать, - это денормализовать поле. То есть - создать реальное поле, которое будет обновляться, чтобы оставаться в синхронизации с полями, из которых оно получено. Я обычно делаю это, переопределяя save on либо моделью с денормализованными полями, либо моделью, из которой она получена:
# 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[...]
Я не тестировал это (мне было бы интересно узнать, работает ли это), но что если определить пользовательский менеджер для 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'
EDIT: Я только что протестировал эту идею, и она отлично работает - не требуется подклассификация django admin!