मैं django टेम्प्लेट में क्वेरी फ़िल्टरिंग कैसे करूँ


83

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

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

अपने टेम्पलेट में मैं करना चाहूंगा

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

लेकिन मुझे अभी पता नहीं चल पाया है कि कैसे फिल्टर लिखना है।

जवाबों:


121

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

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


2
हेलो पीपल २०१४ अब है! लगभग 6 साल बाद जेएस पुस्तकालयों ने भारी प्रगति की है, और डेटा की बड़ी मात्रा में नहीं बल्कि कुछ अच्छी जावा स्क्रिप्ट लाइब्रेरी, या कम से कम AJAX- एड के समर्थन के साथ क्लाइंट के डेटा को फ़िल्टर करना चाहिए।
औरिलाबस

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

यकीन है, लेकिन मैं सिर्फ उन सभी बिंदुओं को इंगित करना चाहता था जो अक्सर कुछ कश्मीर पंक्तियों के साथ काम करते हैं, उपयोगकर्ता के लिए अच्छा इंटरैक्शन एक्सपायरी ब्राउज़र में हो सकता है। और लोगों के लिए भी विशाल डेटा सेट के साथ कुछ हाइब्रिड aproach एक अच्छा समाधान हो सकता है, उदाहरण के लिए कुछ एम के संदर्भ में कुछ ओर सर्वर के लिए और कुछ लाइटर स्टाफ में इस के कुछ ग्राहक पक्ष पर करते हैं।
औरिलाब

9
@ कंडी उन स्थितियों को छोड़कर, जहां आप अनुमतियों के आधार पर सामग्री को फ़िल्टर कर रहे हैं, जो कभी भी क्लाइंट की तरफ से नहीं किया जाएगा। सही?

39

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

@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 %}

मैं इस समाधान की कोशिश कर रहा हूं, लेकिन यह एक त्रुटि को ट्रिगर करता रहता है 'for' statements should use the format 'for x in y': for p in r | people_in_roll_department:d:। कोई विचार?
डायोसनी

@diosney को आप शायद वाक्य वाक्य में ".all" जोड़ सकते हैं। यह "
बातें

12

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

कुछ अन्य संभावित उपाय:

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

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


9

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

इसका एक अच्छा उदाहरण एक 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मॉडल पर किए गए सभी डिफ़ॉल्ट प्रश्नों के खिलाफ एक ही फ़िल्टर लागू करता है और इसलिए ऊपर वर्णित कुछ तकनीकों के समान लचीला नहीं है।


9

इसे असाइनमेंट टैग के साथ हल किया जा सकता है:

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)

4
असाइनमेंट_टैग को Django 2.0
एंड्रियास बर्गस्ट्रॉम में

1

2020 में जवाब की तलाश में किसी के लिए। यह मेरे लिए काम किया।

दृश्य में:

 class InstancesView(generic.ListView):
        model = AlarmInstance
        context_object_name = 'settings_context'
        queryset = Group.objects.all()
        template_name = 'insta_list.html'

        @register.filter
        def filter_unknown(self, aVal):
            result = aVal.filter(is_known=False)
            return result

        @register.filter
        def filter_known(self, aVal):
            result = aVal.filter(is_known=True)
            return result

टेम्पलेट में:

{% for instance in alarm.qar_alarm_instances|filter_unknown:alarm.qar_alarm_instances %}

छद्मकोश में:

For each in model.child_object|view_filter:filter_arg

उम्मीद है की वो मदद करदे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.