2008-10-21 10 views
62

मैं एक Django टेम्पलेट के भीतर से किसी फ़िल्टर किए गए क्वेरी प्रदर्शन करने के लिए, एक दृश्य के भीतर अजगर कोड के बराबर वस्तुओं का एक सेट प्राप्त करने की आवश्यकता:मैं कैसे Django टेम्पलेट्स में क्वेरी को छानने करते हैं

queryset = Modelclass.objects.filter(somekey=foo) 

मेरे टेम्पलेट में मैं

{% for object in data.somekey_set.FILTER %} 

लेकिन मुझे लगता है कि फ़िल्टर को कैसे लिखना है, यह नहीं लगता है।

उत्तर

98

आप ऐसा नहीं कर सकते हैं, जो डिज़ाइन द्वारा है। Django ढांचे लेखकों का उद्देश्य डेटा तर्क से प्रस्तुति कोड का सख्त अलगाव का इरादा है। फ़िल्टरिंग मॉडल डेटा तर्क है, और एचटीएमएल आउटपुट प्रस्तुति तर्क है।

तो आपके पास कई विकल्प हैं। फिल्टरिंग करना सबसे आसान है, फिर परिणाम को render_to_response पर पास करें। या आप अपने मॉडल में एक विधि लिख सकते हैं ताकि आप {% for object in data.filtered_set %} कह सकें। अंत में, आप अपना खुद का टेम्पलेट टैग लिख सकते हैं, हालांकि इस विशिष्ट मामले में मैं इसके खिलाफ सलाह दूंगा।

+2

के लिए धन्यवाद django डिजाइन अवधारणा के स्पष्टीकरण। मैं मॉडल विधि दृष्टिकोण का उपयोग कर रहा हूं। – Ber

+2

हैलो लोग 2014 अब है! लगभग 6 साल बाद जेएस पुस्तकालयों ने बड़ी प्रगति की है, और कुछ अच्छी जावा स्क्रिप्ट लाइब्रेरी, या कम से कम AJAX-ed के समर्थन के साथ क्लाइंट पक्ष पर डेटा की अत्यधिक मात्रा में फ़िल्टर नहीं किया जाना चाहिए। – andi

+1

@andi: मैं निश्चित रूप से यहां तक ​​कि मामूली बड़े डेटा सेट के लिए भी सहमत हूं, उदा। एक मेज में भी हजारों पंक्तियां। लाखों पंक्तियों के साथ डेटाबेस पर काम करने के बाद, निश्चित रूप से सर्वर-साइड फ़िल्टरिंग के लिए निश्चित रूप से एक जगह है :) –

11

मैं नियमित रूप से इस समस्या में भागता हूं और अक्सर "एक विधि जोड़ें" समाधान का उपयोग करता हूं। हालांकि, निश्चित रूप से ऐसे मामले हैं जहां "एक विधि जोड़ें" या "दृश्य में गणना करें" काम न करें (या अच्छी तरह से काम न करें)। जैसे जब आप टेम्पलेट टुकड़ों को कैशिंग कर रहे हैं और इसे उत्पन्न करने के लिए कुछ गैर-तुच्छ डीबी गणना की आवश्यकता है। जब तक आपको आवश्यकता न हो, तब तक आप डीबी काम नहीं करना चाहते हैं, लेकिन आपको तब तक पता नहीं चलेगा जब तक आपको टेम्पलेट तर्क में गहराई न हो।

कुछ अन्य संभावित समाधानों:

  1. {% expr < अभिव्यक्ति> < var_name>% के रूप में} का उपयोग करें टेम्पलेट टैग http://www.djangosnippets.org/snippets/9/ में पाया अभिव्यक्ति अपने स्थानीय गुंजाइश के रूप में अपने टेम्पलेट के प्रसंग के साथ किसी भी कानूनी अजगर अभिव्यक्ति है ।

  2. अपना टेम्पलेट प्रोसेसर बदलें। Jinja2 (http://jinja.pocoo.org/2/) में वाक्यविन्यास है जो लगभग Django टेम्पलेट भाषा के समान है, लेकिन पूर्ण पायथन शक्ति के साथ उपलब्ध है। यह भी तेज़ है। आप यह थोक कर सकते हैं, या आप टेम्पलेट्स पर इसका उपयोग सीमित कर सकते हैं कि आप काम कर रहे हैं, लेकिन डिजाइनर-बनाए रखा पृष्ठों के लिए Django के "सुरक्षित" टेम्पलेट का उपयोग करें।

6

दूसरा विकल्प है कि यदि आप एक फिल्टर है कि आप हमेशा लागू करना चाहते हैं, प्रश्न में मॉडल जो हमेशा फिल्टर करने के लिए परिणाम नहीं दिए लागू होता है पर एक custom manager जोड़ना है।

इस का एक अच्छा उदाहरण एक Event मॉडल है, जहां प्रश्नों का 90% के लिए आप मॉडल आप Event.objects.filter(date__gte=now) की तरह कुछ चाहते करने जा रहे हैं पर करते है, यानि कि आप सामान्य रूप से Events में रुचि आगामी रहे हैं कि कर रहे हैं। यह दिखाई देगा:

class EventManager(models.Manager): 
    def get_query_set(self): 
     now = datetime.now() 
     return super(EventManager,self).get_query_set().filter(date__gte=now) 

और मॉडल में:

class Event(models.Model): 
    ... 
    objects = EventManager() 

लेकिन फिर से, इस Event मॉडल पर किया सभी डिफ़ॉल्ट प्रश्नों के खिलाफ एक ही फिल्टर लागू होता है और इतनी के रूप में से कुछ लचीला नहीं है ऊपर वर्णित तकनीकें।

from django import template 

register = template.Library() 

@register.assignment_tag 
def query(qs, **kwargs): 
    """ template tag which allows queryset filtering. Usage: 
      {% query books author=author as mybooks %} 
      {% for book in mybooks %} 
      ... 
      {% endfor %} 
    """ 
    return qs.filter(**kwargs) 
8

यह एक काम टैग के साथ हल किया जा सकता

@register.filter 
def in_category(things, category): 
    return things.filter(category=category) 

तो मैं कर सकते हैं:

{% for category in categories %} 
    {% for thing in things|in_category:category %} 
    {{ thing }} 
    {% endfor %} 
{% endfor %} 
22

मैं सिर्फ इस तरह एक अतिरिक्त टेम्पलेट टैग को जोड़ने:

+0

मैं इस समाधान का प्रयास कर रहा हूं लेकिन यह एक त्रुटि को ट्रिगर करता रहता है: '' के लिए 'कथन' x में x के लिए प्रारूप 'का उपयोग करना चाहिए: पी में आर के लिए | people_in_roll_department: d'। कोई विचार? – diosney

+1

एक बुरा बग द्वारा स्ट्रक :(https://code.djangoproject.com/ticket/19882 – diosney

संबंधित मुद्दे