2010-02-16 18 views
58

से क्वेरी को छानने मैं इन मॉडल:Django, मॉडल विधि

def Foo(Models.model): 
    size = models.IntegerField() 
    # other fields 

    def is_active(self): 
     if check_condition: 
       return True 
     else: 
       return False 

def Bar(Models.model): 
    foo = models.ForeignKey("Foo") 
    # other fields 

अब मैं बार्स कर रहे हैं कि क्वेरी करना चाहते हैं सक्रिय फू के रूप में इस तरह:

Bar.objects.filter(foo.is_active()) 

मैं ऐसे

के रूप में त्रुटि हो रही है
SyntaxError at/
('non-keyword arg after keyword arg' 

मैं यह कैसे प्राप्त कर सकते हैं?

उत्तर

29

आप मॉडल विधियों या गुणों के खिलाफ क्वेरी नहीं कर सकते हैं। या तो क्वेरी में इसके भीतर मानदंडों का उपयोग करें, या एक सूची समझ या जीनक्स का उपयोग कर पायथन में फ़िल्टर करें।

+6

या उस डेटा को स्टोर करें जिसे आप किसी डेटाबेस फ़ील्ड में फ़िल्टर करना चाहते हैं और जब आपको आवश्यकता है (आमतौर पर सहेजने पर) इसे अपडेट करें। फिर आप इसे किसी भी अन्य फ़ील्ड की तरह फ़िल्टर/सॉर्ट कर सकते हैं। –

+2

यदि मैं विधि क्वेरी के भीतर मानदंडों का दोबारा उपयोग करता हूं, तो मैं DRY कैसे रहूं? मेरे तरीके हमारे व्यापार तर्क के लिए बेहद महत्वपूर्ण हैं और यदि तर्क परिवर्तन कहा जाता है, तो मैं तोड़ने के लिए अपने तरीकों का जोखिम नहीं उठा सकता। डीआरवाई रहना बेहद महत्वपूर्ण है। – Flowpoke

+0

पाइथन में ऐसा करके आप एक संभावित प्रदर्शन कमजोरी पेश करते हैं जब आप क्वेरी फ़िल्टर का उपयोग करते हैं तो यह डीबी स्तर पर किया जाता है, लेकिन जब आप पाइथन स्तर पर करते हैं तो आमतौर पर धीमा होता है। –

10

आप तरीकों पर फ़िल्टर नहीं कर सकते, लेकिन यदि कम महत्वपूर्ण चीज़ों पर is_active विधि कम महत्वपूर्ण चीज़ों पर एक विशेषता की जाँच करता है, आप की तरह Bar.objects.filter(foo__is_active_attribute=True)

+0

मुझे मिल रहा है: फ़ील्ड में कीवर्ड 'is_active_attribute' को हल नहीं किया जा सकता है विकल्प: .... यहां सूचीबद्ध सभी परिवर्तनीय नाम – Hellnar

+1

हाँ, यही कारण है कि मैंने कहा "अगर फू पर is_active विधि एक विशेषता की जांच करता है ..."। फ़िल्टरिंग केवल डेटाबेस फ़ील्ड पर काम करता है, तरीकों से नहीं। तो यदि is_active * विधि के अंदर कुछ विशेषता जांच रहा है * आप उसी फ़िल्टर को अपने फ़िल्टर में देख सकते हैं। यदि यह कुछ और जटिल कर रहा है, तो आप भाग्य से बाहर हैं और एक अलग समाधान खोजने की जरूरत है। यदि आप एक विशिष्ट उत्तर चाहते हैं, तो Foo.is_active() के लिए असली कोड पोस्ट करें। अन्यथा आपको मिलेगा छद्म कोड समाधान जो आपको वर्बैटिम काम करने की उम्मीद नहीं करनी चाहिए। –

13

डबल अंडरस्कोर सिंटैक्स का उपयोग कर सकते हैं मैं इसी तरह की समस्या थी: मैं उपयोग कर रहा हूँ वर्ग आधारित object_list देखें और मुझे मॉडल की विधि से फ़िल्टर करना पड़ा। (डेटाबेस में जानकारी संग्रहीत करना एक विकल्प नहीं था क्योंकि संपत्ति समय पर आधारित थी और मुझे एक cronjob और/या ... कोई रास्ता नहीं बनाना होगा)

मेरा उत्तर अप्रभावी है और मैं नहीं करता जानें कि यह बड़े डेटा पर कैसे स्केल करेगा; लेकिन, यह काम करता है:

q = Model.objects.filter(...)... 
# here is the trick 
q_ids = [o.id for o in q if o.method()] 
q = q.filter(id__in=q_ids) 
+4

यह एकमात्र तरीका है जिसे मैं DRY रहने के लिए देखता हूं, हालांकि यह बड़े डेटासेट के साथ प्रदर्शन में बाधा डालता है (याद रखें कि सूचियों को स्मृति में संग्रहीत किया जाता है) – Ben

24

आप एक कस्टम प्रबंधक का भी उपयोग कर सकते हैं। तो फिर तुम कुछ इस तरह चला सकते हैं:

Bar.objects.foo_active() 

और तुम सब करने की है:

class BarManager(models.Manager): 
    def foo_active(self): 
     # use your method to filter results 
     return you_custom_queryset 

चेक बाहर docs

+0

आपका कोड एक बहुत अच्छा परिचय है! धन्यवाद – doniyor

0
class Page(models.Model): 
    category = models.ForeignKey(Category) 
    title = models.CharField(max_length=128) 
    url = models.URLField() 
... 

class Category(models.Model): 
    ... 
    open = models.BooleanField(default=True) 

क्या आप इस प्रकार की स्थितियों के लिए सरल फ़िल्टर का उपयोग कर सकते हैं।

Page.objects.filter(category__open=True) 
संबंधित मुद्दे