[django] Django 관리자 : 데이터베이스 필드가없는 사용자 지정 list_display 필드 중 하나로 정렬하는 방법

# 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 관리자 서브 클래 싱이 필요하지 않습니다!


답변

내가 생각할 수있는 유일한 방법은 필드를 비정규 화하는 것입니다. 즉, 파생 된 필드와 동기화 상태를 유지하도록 업데이트되는 실제 필드를 만듭니다. 일반적으로 비정규 화 된 필드가있는 모델 또는 파생 된 모델 중 하나에 대한 저장을 재정 의하여이 작업을 수행합니다.

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


답변