Django ManyToMany फ़िल्टर ()


131

मेरे पास एक मॉडल है:

class Zone(models.Model):
    name = models.CharField(max_length=128)
    users = models.ManyToManyField(User, related_name='zones', null=True, blank=True)

और मुझे इनकी तर्ज पर एक फिल्टर का संरक्षण करने की आवश्यकता है:

u = User.objects.filter(...zones contains a particular zone...)

यह उपयोगकर्ता पर एक फिल्टर होना चाहिए और इसे एक एकल फ़िल्टर पैरामीटर होना चाहिए। इसका कारण यह है कि मैं व्यवस्थापक उपयोगकर्ता चैनल को फ़िल्टर करने के लिए एक URL querystring का निर्माण कर रहा हूं:http://myserver/admin/auth/user/?zones=3

ऐसा लगता है कि यह सरल होना चाहिए लेकिन मेरा दिमाग सहयोग नहीं कर रहा है!


8
मुझे यकीन है कि अगर मैं आप प्राप्त नहीं कर रहा हूँ सही - नहीं है User.objects.filter(zones__id=<id>)या User.objects.filter(zones__in=<id(s)>)इस के लिए अच्छा है?
टॉमाज़ ज़िलिओस्की 21

यह ठीक है :) BTW User.objects.filter(zones__in=<id(s)>)शायद होना चाहिएUser.objects.filter(zones__id__in=<id(s)>)
टॉमस ज़ीलिस्की

21
किसी को भी Googling के लिए इंगित करना चाहता था, कि यह केवल तभी काम करता है यदि संबंधित_नाम सेट है। उदाहरण के लिए, Zone_set काम नहीं करेगा। उस पर एक अच्छा आधा घंटे बर्बाद कर दिया :-)

जवाबों:


155

टॉमस ने जो कहा उसे ठीक करते हुए।

कई -कई और कई-से-एक परीक्षणों FOO__in=...में स्टाइल फ़िल्टर के कई उदाहरण हैं । यहाँ आपकी विशिष्ट समस्या के लिए वाक्य रचना है:

users_in_1zone = User.objects.filter(zones__id=<id1>)
# same thing but using in
users_in_1zone = User.objects.filter(zones__in=[<id1>])

# filtering on a few zones, by id
users_in_zones = User.objects.filter(zones__in=[<id1>, <id2>, <id3>])
# and by zone object (object gets converted to pk under the covers)
users_in_zones = User.objects.filter(zones__in=[zone1, zone2, zone3])

डबल अंडरस्कोर (__) सिंटैक्स का उपयोग क्वेरी के साथ काम करते समय सभी जगह किया जाता है ।


धन्यवाद @ मक्सम कुछ उदाहरणों के लिए अधिक वर्तमान लिंक के साथ अपडेट किया गया।
istruble

9
डबल अंडरस्कोर (अरे 3 घंटे है कि एक को खो दिया है।)
reabow

क्या आप कृपया कह सकते हैं, यदि मैं उन उपयोगकर्ताओं को क्या करना चाहता हूं जो जोनों के एक समूह में हैं, तो उनमें से कोई भी नहीं? कहते हैं खोज करने वाले उपयोगकर्ता Zone1, zone3 में हैं, .. और क्षेत्र 10 की सुविधा देता है
FRR

इसके ...__inबाद के उदाहरण देखें # filtering on a few zones, by id। वे कई आईडी / ऑब्जेक्ट (इस मामले में) के लिए फ़िल्टरिंग दिखाते हैं। ज़ोन 1, ज़ोन 3, और ज़ोन 10 आईडी / ऑब्जेक्ट्स के बारे में ध्यान से देखें। या यदि आवश्यकता हो तो 4 न जोड़ें।
istruble

धन्यवाद। मैं केवल एकल मान के विरुद्ध फ़िल्टर कर रहा था, बजाय एकल मान वाले सरणी के।
जिप्रो

36

ध्यान दें कि यदि उपयोगकर्ता क्वेरी में उपयोग किए गए कई ज़ोन में हो सकता है, तो आप शायद .distinct () जोड़ना चाहते हैं। अन्यथा आपको कई बार एक उपयोगकर्ता मिलता है:

users_in_zones = User.objects.filter(zones__in=[zone1, zone2, zone3]).distinct()

1

ऐसा करने का एक और तरीका मध्यवर्ती तालिका के माध्यम से जा रहा है। मैं इसे इस तरह से Django ORM के भीतर व्यक्त करूंगा:

UserZone = User.zones.through

# for a single zone
users_in_zone = User.objects.filter(
  id__in=UserZone.objects.filter(zone=zone1).values('user'))

# for multiple zones
users_in_zones = User.objects.filter(
  id__in=UserZone.objects.filter(zone__in=[zone1, zone2, zone3]).values('user'))

यह अच्छा होगा यदि इसे .values('user')निर्दिष्ट की आवश्यकता नहीं है , लेकिन Django (संस्करण 3.0.7) को इसकी आवश्यकता लगती है।

उपरोक्त कोड SQL उत्पन्न करने वाले को समाप्त करेगा जो कुछ इस तरह दिखता है:

SELECT * FROM users WHERE id IN (SELECT user_id FROM userzones WHERE zone_id IN (1,2,3))

जो अच्छा है क्योंकि इसमें कोई मध्यवर्ती जुड़ाव नहीं है जिसके कारण डुप्लिकेट उपयोगकर्ता वापस आ सकते हैं


हिया। यह अपने आप में एक जवाब नहीं है। आपको एक अतिरिक्त आंशिक उत्तर जोड़ने के बजाय एक टिप्पणी जोड़नी चाहिए या QB के उत्तर को संपादित करना चाहिए।
एंडी बेकर

हाँ - यदि आप अपना उत्तर संपादित करना चाहते हैं तो यह अपने आप में पूर्ण है (जब तक कि आपको QB के उत्तर को संपादित करने के लिए पर्याप्त कर्म नहीं मिला है?) तो वह सबसे अच्छा दांव होगा। आदर्श रूप से StackOverflow पर "एक सही उत्तर" है। यह आमतौर पर बड़े करीने से काम नहीं करता है, लेकिन यह लक्ष्य के लिए लायक है।
एंडी बेकर

@AndyBaker सहमत! मुंहतोड़ जवाब में QB का जवाब शायद istruble के जवाब पर टिप्पणी होना चाहिए, जबकि मुझे लगता है कि मेरा अलग वार का जवाब देने के लिए पर्याप्त है, लेकिन अच्छी तरह से
सैम मेसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.