2009-06-01 18 views
12

मैं एक Django एप्लिकेशन लिख रहा हूं जिसमें लोगों के लिए एक मॉडल है, और मैंने एक झटका मारा है। मैं कई लोगों से कई रिश्तों का उपयोग करके लोगों को भूमिका वस्तुएं सौंप रहा हूं - जहां भूमिकाओं का नाम और वजन होता है। मैं अपनी भारी भूमिका के वजन से लोगों की सूची को ऑर्डर करना चाहता हूं। अगर मैं People.objects.order_by ('- भूमिकाएं' वजन) करता हूं, तो मुझे डुप्लिकेट मिलते हैं जब लोगों को उनके लिए कई भूमिकाएं सौंपी जाती हैं।Django: कई से कई फ़ील्ड द्वारा मॉडल को ऑर्डर करें

मेरा प्रारंभिक विचार भारी-भूमिका-भार नामक एक असामान्य क्षेत्र को जोड़ना था - और इसके द्वारा क्रमबद्ध करें। यह तब भी अपडेट किया जा सकता है जब उपयोगकर्ता द्वारा नई भूमिका को जोड़ा या हटा दिया गया हो। हालांकि, यह पता चला है कि जब भी कई ToTManyField को Django (yet, वैसे भी) में अद्यतन किया जाता है, तो कस्टम कार्रवाई करने का कोई तरीका नहीं है।

तो, मैंने सोचा कि मैं पूरी तरह से ओवरबोर्ड पर जा सकता हूं और इसे संभालने के लिए एक कस्टम फ़ील्ड, डिस्क्रिप्टर और मैनेजर लिख सकता हूं - लेकिन यह बहुत मुश्किल लगता है जब ManyRelatedManager को कईToManyField के लिए गतिशील रूप से बनाया गया है।

मैं कुछ चालाक एसक्यूएल के साथ आने की कोशिश कर रहा हूं जो मेरे लिए यह कर सकता है - मुझे यकीन है कि यह सबक्वायरी (या कुछ) के साथ संभव है, लेकिन मैं इसके बारे में चिंतित हूं कि यह संगत नहीं होगा डाटाबेस बैकएंड्स Django का समर्थन करता है।

क्या किसी ने इससे पहले किया है - या कोई विचार है कि इसे कैसे प्राप्त किया जा सकता है? एसक्यूएल में

उत्तर

11

Django 1.1 (वर्तमान में बीटा) aggregation समर्थन जोड़ता है। आपकी क्वेरी कुछ के साथ की जा सकती है जैसे:

from django.db.models import Max 
People.objects.annotate(max_weight=Max('roles__weight')).order_by('-max_weight') 

यह डुप्लीकेट लौटने के बिना लोगों को उनकी भारी भूमिकाओं से रोकता है।

उत्पन्न क्वेरी है:

SELECT people.id, people.name, MAX(role.weight) AS max_weight 
FROM people LEFT OUTER JOIN people_roles ON (people.id = people_roles.people_id) 
      LEFT OUTER JOIN role ON (people_roles.role_id = role.id) 
GROUP BY people.id, people.name 
ORDER BY max_weight DESC 
+0

मैं बस क्या था:

class Role(models.Model): pass class PersonRole(models.Model): weight = models.IntegerField() person = models.ForeignKey('Person') role = models.ForeignKey(Role) class Meta: # if you have an inline configured in the admin, this will # make the roles order properly ordering = ['weight'] class Person(models.Model): roles = models.ManyToManyField('Role', through='PersonRole') def ordered_roles(self): "Return a properly ordered set of roles" return self.roles.all().order_by('personrole__weight') 

इस की मदद से आप कुछ ऐसा कहना खोज रहे हैं मैं Django 1.1 नहीं चला रहा हूं, लेकिन मैं अपने कस्टम मैनेजर में उस एसक्यूएल का उपयोग कर सकता हूं। धन्यवाद :) –

1

कुछ इस तरह:

select p.*, max (r.Weight) as HeaviestWeight 
from persons p 
inner join RolePersons rp on p.id = rp.PersonID 
innerjoin Roles r on rp.RoleID = r.id 
group by p.* 
order by HeaviestWeight desc 

नोट: पी। द्वारा समूह * एसक्यूएल की अपनी बोली ने उसकी अनुमति नहीं जा सकता है। यदि ऐसा है, तो बस तालिका पी में सभी कॉलम सूचीबद्ध करें जिन्हें आप चुनिंदा खंड में उपयोग करना चाहते हैं।

नोट: यदि आप केवल पीआईडी ​​द्वारा समूहबद्ध हैं, तो आप अपने चुने हुए खंड में पी में अन्य कॉलम के लिए कॉल नहीं कर पाएंगे।

मुझे नहीं पता कि यह Django के साथ कैसे इंटरैक्ट करता है।

6

यहाँ एक एनोटेशन के बिना यह करने के लिए एक तरीका है:

>>> person = Person.objects.get(id=1) 
>>> roles = person.ordered_roles() 
संबंधित मुद्दे