Django में, एक गतिशील क्षेत्र लुकअप के साथ एक क्वेरी कैसे फ़िल्टर करता है?


160

एक वर्ग दिया:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=20)

क्या यह संभव है, और यदि ऐसा है तो, QuerySet को गतिशील तर्कों के आधार पर कैसे फ़िल्टर किया जाए? उदाहरण के लिए:

 # Instead of:
 Person.objects.filter(name__startswith='B')
 # ... and:
 Person.objects.filter(name__endswith='B')

 # ... is there some way, given:
 filter_by = '{0}__{1}'.format('name', 'startswith')
 filter_value = 'B'

 # ... that you can run the equivalent of this?
 Person.objects.filter(filter_by=filter_value)
 # ... which will throw an exception, since `filter_by` is not
 # an attribute of `Person`.

जवाबों:


310

इस समस्या को हल करने के लिए पायथन के तर्क विस्तार का उपयोग किया जा सकता है:

kwargs = {
    '{0}__{1}'.format('name', 'startswith'): 'A',
    '{0}__{1}'.format('name', 'endswith'): 'Z'
}

Person.objects.filter(**kwargs)

यह एक बहुत ही सामान्य और उपयोगी पायथन मुहावरा है।


6
बस एक त्वरित गोथा सिर-अप: सुनिश्चित करें कि kwargs में तार प्रकार के हैं जो यूनिकोड नहीं है, अन्यथा फ़िल्टर () में गड़बड़ी होगी।
स्टीव जालिम

1
@santiagobasulto यह भी एक पैरामीटर पैकिंग / unpacking, और उसके रूपांतरों के लिए भेजा है।
डेनियल नाब

7
अच्छा, अच्छा और अच्छा !
ऑस्कर मेडेरोस

5
@DanielNaab लेकिन यह केवल काम कर रहे kwargs पर काम करेगा और शर्त फ़िल्टरिंग, OR स्थिति के लिए कोई विकल्प।
Prateek099

3
@prateek आप हमेशा Q ऑब्जेक्ट का उपयोग कर सकते हैं: stackoverflow.com/questions/13076822/…
deecodameeko

6

एक सरल उदाहरण:

Django के सर्वेक्षण ऐप में, मुझे पंजीकृत उपयोगकर्ताओं को दिखाते हुए एक HTML चयन सूची चाहिए थी। लेकिन क्योंकि हमारे पास 5000 पंजीकृत उपयोगकर्ता हैं, मुझे क्वेरी मानदंड के आधार पर उस सूची को फ़िल्टर करने के लिए एक तरीका चाहिए (जैसे कि कुछ लोग जो एक निश्चित कार्यशाला पूरी करते हैं)। सर्वेक्षण तत्व को पुन: प्रयोग करने योग्य बनाने के लिए, मुझे सर्वेक्षण प्रश्न बनाने वाले व्यक्ति के लिए उस मानदंड को उस प्रश्न के साथ संलग्न करने में सक्षम होना चाहिए (ऐप में क्वेरी को हार्ड-कोड नहीं करना है)।

मैं जिस समाधान के साथ आया हूं वह 100% उपयोगकर्ता के अनुकूल नहीं है (क्वेरी बनाने के लिए किसी तकनीकी व्यक्ति की मदद की आवश्यकता है) लेकिन यह समस्या को हल करता है। प्रश्न बनाते समय, संपादक एक शब्दकोश को एक कस्टम फ़ील्ड में दर्ज कर सकता है, जैसे:

{'is_staff':True,'last_name__startswith':'A',}

उस स्ट्रिंग को डेटाबेस में संग्रहीत किया जाता है। व्यू कोड में, यह वापस आता है self.question.custom_query। उस का मान एक स्ट्रिंग है जो एक शब्दकोश जैसा दिखता है । हम इसे फिर से eval () के साथ एक वास्तविक शब्दकोष में बदल देते हैं और फिर ** क्वार्ग्स के साथ क्वेरी में इसे भर देते हैं:

kwargs = eval(self.question.custom_query)
user_list = User.objects.filter(**kwargs).order_by("last_name")   

मैं सोच रहा हूं कि यह एक कस्टम ModelField / FormField / WidgetField बनाने में क्या होगा जिसने उपयोगकर्ता को GUI की ओर से अनुमति देने के लिए व्यवहार को लागू किया है, मूल रूप से एक क्वेरी का निर्माण "मूल रूप से" करता है, कभी भी वास्तविक पाठ को नहीं देखता, लेकिन इंटरफ़ेस का उपयोग करके ऐसा करो। एक साफ सुथरी परियोजना की तरह लगता है ...
टी। स्टोन

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

5
-1 eval()उपयोगकर्ता आयात पर कॉल करना एक बुरा विचार है, भले ही आप अपने उपयोगकर्ताओं पर पूरा भरोसा करते हों। एक JSON क्षेत्र यहां एक बेहतर विचार होगा।
जॉन कार्टर

5

Django.db.models.Q वास्तव में एक Django तरीके से आप क्या चाहते हैं।


7
क्या आप (या कोई) गतिशील फ़ील्ड नामों का उपयोग करके Q ऑब्जेक्ट का उपयोग करने का एक उदाहरण प्रदान कर सकते हैं?
जैकबर्नियर

3
यह डैनियल नाब के उत्तर के समान है केवल अंतर यह है कि आप क्यू ऑब्जेक्ट कंस्ट्रक्टर में तर्कों को पास करते हैं। Q(**filters), यदि आप क्यू वस्तुओं को गतिशील रूप से बनाना चाहते हैं, तो आप उन्हें एक सूची में डाल सकते हैं और उपयोग कर सकते हैं .filter(*q_objects), या क्यू ऑब्जेक्ट्स को संयोजित करने के लिए बिटवाइज़ ऑपरेटरों का उपयोग कर सकते हैं।
विल एस

5
इस जवाब में वास्तव में ओपी की समस्या को हल करने के लिए क्यू का उपयोग करने का एक उदाहरण शामिल होना चाहिए।
pdoherty926

-2

वास्तव में जटिल खोज फ़ॉर्म यह इंगित करते हैं कि एक सरल मॉडल इसे खोदने की कोशिश कर रहा है।

कैसे, ठीक, क्या आप स्तंभ नाम और संचालन के लिए मान प्राप्त करने की अपेक्षा करते हैं? आप के मूल्यों कहां मिल सकते हैं 'name'एक 'startswith'?

 filter_by = '%s__%s' % ('name', 'startswith')
  1. एक "खोज" रूप? आप जा रहे हैं - क्या? - नामों की सूची से नाम चुनें? ऑपरेशन की सूची से ऑपरेशन चुनें? ओपन एंडेड होते समय, अधिकांश लोग इस भ्रामक और कठिन उपयोग को पाते हैं।

    ऐसे कॉलम में कितने फिल्टर होते हैं? 6? 12? 18?

    • कुछ? एक जटिल पिक-लिस्ट का कोई मतलब नहीं है। कुछ क्षेत्रों और कुछ बयानों समझ में आता है।
    • एक बड़ी संख्या में? आपका मॉडल सही नहीं लगता। ऐसा लगता है कि "फ़ील्ड" वास्तव में एक अन्य तालिका में एक पंक्ति की कुंजी है, न कि एक स्तंभ।
  2. विशिष्ट फिल्टर बटन। रुको ... यह उसी तरह है जिस तरह से Django एडमिन काम करता है। विशिष्ट फ़िल्टर बटन में बदल जाते हैं। और ऊपर जैसा ही विश्लेषण लागू होता है। कुछ फिल्टर समझ में आता है। बड़ी संख्या में फिल्टर का मतलब आमतौर पर एक प्रकार का पहला सामान्य रूप उल्लंघन होता है।

बहुत सारे समान क्षेत्रों का अर्थ अक्सर अधिक पंक्तियाँ और कम क्षेत्र होना चाहिए था।


9
सम्मान के साथ, यह डिजाइन के बारे में कुछ भी जाने बिना सिफारिशें करने के लिए उचित है। आवश्यकताओं को पूरा करने के लिए यह एप्लिकेशन "बस कार्यान्वित" करने के लिए खगोलीय (> 200 ऐप्स ^ 21 फ़ॉज़) कार्यों को भूल जाएगा। आप उद्देश्य और इरादे को उदाहरण में पढ़ रहे हैं; आपको नहीं करना चाहिए :)
ब्रायन एम। हंट

2
मैं बहुत से ऐसे लोगों से मिलता हूं जिन्हें लगता है कि उनकी समस्या को हल करने के लिए तुच्छ होगा यदि केवल चीजें (ए) अधिक सामान्य और (बी) ने जिस तरह से कल्पना की थी, उसी तरह से काम किया। यह रास्ता अंतहीन हताशा है क्योंकि चीजें वैसी नहीं हैं जैसी उन्होंने कल्पना की थी। मैंने "फ्रेमवर्क को ठीक करने" से बहुत अधिक विफलताओं को देखा है।
S.Lott

2
डैनियल की प्रतिक्रिया के अनुसार चीजें अपेक्षित और वांछित काम करती हैं। मेरा सवाल वाक्य रचना के बारे में था, न कि डिज़ाइन के बारे में। यदि मेरे पास डिज़ाइन लिखने का समय होता, तो मैंने ऐसा किया होता। मुझे यकीन है कि आपका इनपुट मददगार होगा, हालांकि यह सिर्फ एक व्यावहारिक विकल्प नहीं है।
ब्रायन एम। हंट

8
S.Lott, आपका उत्तर इस प्रश्न का दूरस्थ रूप से उत्तर नहीं देता है। यदि आपको कोई उत्तर नहीं पता है, तो कृपया प्रश्न को अकेले छोड़ दें। जब आपके पास डिज़ाइन का बिल्कुल शून्य ज्ञान हो, तो अवांछित डिज़ाइन सलाह का जवाब न दें!
slypete

2
@slypete: अगर डिज़ाइन में बदलाव से समस्या दूर हो जाती है, तो समस्या हल हो जाती है। खराब डिज़ाइन पर आधारित पथ के साथ जारी रहना आवश्यक से अधिक महंगा और जटिल है। मूल कारण समस्याओं को हल करना अन्य समस्याओं को हल करने से बेहतर है जो खराब डिजाइन निर्णयों से उपजी हैं। मुझे खेद है कि आपको मूल-कारण विश्लेषण पसंद नहीं है। लेकिन जब कुछ वास्तव में कठिन होता है, तो आमतौर पर इसका मतलब है कि आप गलत चीज़ को शुरू करने की कोशिश कर रहे हैं।
S.Lott
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.