Django व्यवस्थापक: कस्टम लिस्ट_डिसप्ले फ़ील्ड में से एक को कैसे सॉर्ट करना है जिसमें कोई डेटाबेस फ़ील्ड नहीं है


122
# 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 को बदलते हैं - यह अपेक्षा के अनुरूप काम करता है!


"मजेदार बात: यदि आप इस स्तंभ पर छाँटने के लिए ब्राउज़र में url को बदलते हैं - यह अपेक्षा के अनुरूप काम करता है!" आपका मतलब है: / व्यवस्थापक / myapp / ग्राहक /? Ot = asc & o = 2 क्या आप सुनिश्चित हैं?
एंडी बेकर

हाँ, दोनों asc और dsc। शायद यह सिर्फ दशमलव के साथ काम करता है।
mike_k

मुझे नहीं लगता कि यह कई पृष्ठों के साथ काम करेगा।
Seibert

जवाबों:


159

मुझे इस समस्या का ग्रेग समाधान पसंद था, लेकिन मैं यह बताना चाहूंगा कि आप सीधे एडमिन में ही काम कर सकते हैं:

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'

इस तरह आप केवल व्यवस्थापक इंटरफ़ेस के अंदर एनोटेट करते हैं। हर उस क्वेरी से नहीं जो आप करते हैं।


5
हां, यह एक बेहतर तरीका है। :)
ग्रेग

2
इस उत्तर पर एक सुझाया गया संपादन है । मैंने इसे अस्वीकार करने के लिए मतदान किया क्योंकि इसने बहुत अधिक पाठ हटा दिए। मुझे Django का पता नहीं है, मुझे पता नहीं है कि प्रस्तावित कोड परिवर्तन ध्यान देने योग्य है या नहीं।
गिल्स एसओ- बुराई को रोकना '

1
@ सुझाए गए संपादन एक सरल संख्या के बारे में सही है_ऑफ्स की परिभाषा। यह काम करता है: def number_of_orders(self, obj): return obj.order__count
निल्स

1
ज़ोर से नहीं कि get_queryset()बजाय हो सकता है queryset()?
Mariusz Jamro

2
Dj_queryset (स्वयं, अनुरोध) मिलना चाहिए: ... Django 1.6+ के लिए
माइकल

50

मैंने इसका परीक्षण नहीं किया है (यदि यह काम करता है, तो मुझे यह जानने में दिलचस्पी होगी), लेकिन एक कस्टम प्रबंधक को परिभाषित करने के बारे में क्या है 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 admin की आवश्यकता नहीं है!


1
स्वीकार किए गए की तुलना में यह बेहतर उत्तर है। जिस समस्या को मैंने स्वीकार किया है उसे लागू करने में भाग गया जब आप व्यवस्थापक स्तर पर उस अपडेट किए गए क्वेरीसेट के साथ कुछ खोजते हैं, तो इसमें बहुत अधिक समय लगता है और इसके परिणाम के लिए गलत गणना के साथ भी आता है।
म्यूटेंट

0

जिस तरह से मैं सोच सकता हूं वह एकमात्र तरीका है क्षेत्र को बदनाम करना। वह है - एक वास्तविक फ़ील्ड बनाएं जो उन क्षेत्रों के साथ सिंक में रहने के लिए अपडेट हो जाता है जिनसे यह प्राप्त होता है। मैं आम तौर पर यह प्रतिरूपित क्षेत्रों के साथ मॉडल को बचाने के लिए ओवरराइड करके करता हूं या जिस मॉडल से यह निकलता है:

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

1
यह निश्चित रूप से काम करना चाहिए, लेकिन अतिरिक्त डीबी क्षेत्र में शामिल होने के कारण इसे स्वीकार नहीं किया जा सकता है। क्वेरी-सेट लाइन के अंत में गुम .count () भी नोट करें।
mike_k 17

गिनती तय ()। एकमात्र अन्य समाधान (कंट्राबासिंग के बड़े विखंडू में कमी) एक जेकरी / अजेक्सी हैक होगा।
एंडी बेकर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.