मैं Django में दिनांक श्रेणी द्वारा क्वेरी ऑब्जेक्ट्स को कैसे फ़िल्टर करूं?


248

मुझे एक मॉडल में एक फ़ील्ड मिला है जैसे:

class Sample(models.Model):
    date = fields.DateField(auto_now=False)

अब, मुझे वस्तुओं को एक तिथि सीमा द्वारा फ़िल्टर करने की आवश्यकता है।

मैं उन सभी वस्तुओं को कैसे फ़िल्टर करूं जिनके बीच दिनांक है 1-Jan-2011और 31-Jan-2011?

जवाबों:


411

उपयोग

Sample.objects.filter(date__range=["2011-01-01", "2011-01-31"])

या यदि आप सिर्फ महीने के हिसाब से छानने की कोशिश कर रहे हैं:

Sample.objects.filter(date__year='2011', 
                      date__month='01')

संपादित करें

जैसा कि बर्नहार्ड वालेंट ने कहा, यदि आप एक क्वेरीसेट चाहते हैं जो आपको बाहर करता है तो specified range endsआपको उसके समाधान पर विचार करना चाहिए , जो gt / lt (अधिक से अधिक / कम-से-अधिक) का उपयोग करता है।


डेट 1 का डेटटाइप क्या है? मुझे अब डेटटाइम ऑब्जेक्ट मिल गया है।
user469652

8
@dcordjer: Additinally में कहा जाना चाहिए कि __rangeइसमें बॉर्डर्स (जैसे sql's BETWEEN) शामिल हैं, अगर आप बॉर्डर नहीं चाहते हैं तो इसमें शामिल हैं कि आपको मेरे gt / lt सॉल्यूशन के साथ जाना होगा ...
बर्नहार्ड वलेंट

क्या यह स्वाभाविक रूप से किसी क्रम में क्रमबद्ध है? यदि हां, तो कौन सा आदेश? धन्यवाद।
रिचर्ड डन

1
@RichardDunn ऑर्डरिंग आपके मॉडल के डिफॉल्ट ऑर्डर के आधार पर होगी, या यदि आप उपर्युक्त द्वारा order_byउत्पन्न पर उपयोग करते हैं । मैंने वर्षों में Django का उपयोग नहीं किया है। QuerySetfilter
11:11

date__range के लिए आपको अगले महीने की 01 तारीखों की आवश्यकता है। यहां डाक्यूमेंटेशन का एक लिंक दिया गया है जो यह बताता है कि यह दिनांक का 00: 00: 00.0000 में अनुवाद करता है, इसलिए आपकी सीमा में अंतिम दिन शामिल नहीं है। docs.djangoproject.com/en/1.10/ref/models/querysets/#range इस मामले में मैं उपयोग करता हूं: date__range = ["% s-% s-1"% (वर्ष, माह), "% s-% s- 1 "% (वर्ष, int (माह) +1)]
13

195

आप वस्तुओं केfilter साथ django का उपयोग कर सकते हैं :datetime.date

import datetime
samples = Sample.objects.filter(sampledate__gte=datetime.date(2011, 1, 1),
                                sampledate__lte=datetime.date(2011, 1, 31))

दिन 1 और 31 सहित सब कुछ पाने के लिए, हमें जीटीई का सही उपयोग करना होगा?
सैम स्टोलिंगा

1
क्रोड्जेर पर इस पद्धति का उपयोग करने का एक लाभ यह है कि आप इसे स्ट्रिंग के बजाय डेटाइम ऑब्जेक्ट पास कर सकते हैं।
ब्रायन कुंग

79

जब एक फ़िल्टर के साथ django पर्वतमाला करते हैं, तो सुनिश्चित करें कि आप किसी डेट ऑब्जेक्ट बनाम डेटाइम ऑब्जेक्ट का उपयोग करने के बीच का अंतर जानते हैं। __ेंज तिथियों पर सम्मिलित है, लेकिन यदि आप अंतिम तिथि के लिए एक डेटाइम ऑब्जेक्ट का उपयोग करते हैं तो इसमें उस दिन के लिए प्रविष्टियां शामिल नहीं होंगी यदि समय निर्धारित नहीं है।

    startdate = date.today()
    enddate = startdate + timedelta(days=6)
    Sample.objects.filter(date__range=[startdate, enddate])

उन तिथियों पर प्रविष्टियों सहित सभी प्रविष्टियों को रिटर्न से एंडडेट पर लौटाता है। खराब उदाहरण चूंकि यह भविष्य में एक सप्ताह में प्रविष्टियां लौटा रहा है, लेकिन आपको बहाव मिलता है।

    startdate = datetime.today()
    enddate = startdate + timedelta(days=6)
    Sample.objects.filter(date__range=[startdate, enddate])

दिनांक फ़ील्ड के लिए सेट किए गए समय के आधार पर प्रविष्टियों के 24 घंटे के मूल्य की अनुपलब्धता होगी।


5
मुझे लगता है कि यह ध्यान रखना महत्वपूर्ण है कि किसी dateवस्तु को कैसे आयात किया जाए : >>> from datetime import date >>> startdate = date.today()
एलेक्स स्पेंसर

19

आप DateTimeField/dateऑब्जेक्ट तुलना में परिशुद्धता की कमी के कारण "प्रतिबाधा बेमेल" प्राप्त कर सकते हैं - जो कि रेंज का उपयोग करते समय हो सकता है - रेंज में अंतिम तिथि में एक दिन जोड़ने के लिए एक datetime.timedelta का उपयोग करके । यह इस तरह काम करता है:

start = date(2012, 12, 11)
end = date(2012, 12, 18)
new_end = end + datetime.timedelta(days=1)

ExampleModel.objects.filter(some_datetime_field__range=[start, new_end])

जैसा कि पहले चर्चा की गई थी, इस तरह से कुछ किए बिना आखिरी दिन रिकॉर्ड को नजरअंदाज कर दिया जाता है।

के उपयोग से बचने के लिए संपादित किया जाता है datetime.combine- DateTimeFieldथ्रोअवे (और भ्रामक) datetimeवस्तुओं के साथ खिलवाड़ करने के बजाय, एक के खिलाफ तुलना करने पर दिनांक उदाहरणों के साथ छड़ी करने के लिए अधिक तर्कसंगत लगता है । नीचे टिप्पणियों में आगे की व्याख्या देखें।


1
वहाँ एक भयानक Delorean पुस्तकालय है जो इसे एक ट्रंकेशन विधि के साथ सरल
बनाता है

@tojjer: होनहार लग रहा है, हम यद्यपि यहाँ ट्रंकट विधि का उपयोग कैसे करते हैं?
यूगीन

@ यूजीन: मैंने इसे अभी-अभी फिर से खोजा, उन सभी महीनों के बाद, और आप सही हैं कि यह वास्तव में इस स्थिति में मदद नहीं करता है। इसके बारे में एकमात्र तरीका जिसके बारे में मैं सोच सकता हूं, वह मेरी मूल प्रतिक्रिया में सुझाया गया है, जो डेटाइम मॉडल फ़ील्ड के विरुद्ध तुलना के लिए अतिरिक्त 'पैडिंग' की आपूर्ति करना है जब आप किसी दिनांक उदाहरण के विरुद्ध फ़िल्टर कर रहे हों। यह ऊपर के रूप में datetime.combine विधि के माध्यम से किया जा सकता है, लेकिन मैंने पाया है कि सीमा में प्रारंभ / समाप्ति तिथि को या तो समयबद्धता (दिन = 1) जोड़कर विसंगति को समायोजित करना थोड़ा सरल हो सकता है - - समस्या पर निर्भर करता है।
trojjer

तो Example.objects.filter(created__range=[date(2014, 1, 1), date(2014, 2, 1)])इसमें बनाई गई वस्तुओं को शामिल नहीं किया जाएगा date(2014, 2, 1), जैसा कि @cademan ने मदद से समझाया। लेकिन यदि आपने एक दिन जोड़कर अंतिम तिथि बढ़ाई है, तो आपको उन लापता वस्तुओं (और date(2014, 2, 2)समान रूप से क्विक के कारण बनाई गई वस्तुओं को आसानी से छोड़ने वाली वस्तुओं ) को कवर करने के लिए एक क्वेरीसेट मिलेगा । यहाँ कष्टप्रद बात यह है कि निर्दिष्ट 'मैनुअल' श्रेणी created__gte ... created__lte=date(2014, 2, 1)या तो काम नहीं करती है, जो निश्चित रूप से काउंटर-सहज आईएमएचओ है।
trojjer

1
@tojjer: datetime_field__range = [delorean.parse ('2014-01-01'), तारीख, delorean.parse ('2014-02-01')। तारीख] मेरे लिए काम करती है
यूजीन

1

आसान है,

YourModel.objects.filter(YOUR_DATE_FIELD__date=timezone.now())

मेरे लिये कार्य करता है


3
यह स्पष्टता के लिए भी मेरे लिए काम किया, noobs के लिए: (date__date = ...) का अर्थ है ({} whateverColumnTheDateIsCalled __ तारीख)
रयान dines

2
ओपी ने हालांकि एक सीमा के लिए कहा
अलियासव

1

इसे और अधिक लचीला बनाने के लिए, आप नीचे एक FilterBackend डिज़ाइन कर सकते हैं:

class AnalyticsFilterBackend(generic_filters.BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        predicate = request.query_params # or request.data for POST

        if predicate.get('from_date', None) is not None and predicate.get('to_date', None) is not None:
            queryset = queryset.filter(your_date__range=(predicate['from_date'], predicate['to_date']))

        if predicate.get('from_date', None) is not None and predicate.get('to_date', None) is None:
            queryset = queryset.filter(your_date__gte=predicate['from_date'])

        if predicate.get('to_date', None) is not None and predicate.get('from_date', None) is None:
            queryset = queryset.filter(your_date__lte=predicate['to_date'])
        return queryset

-2

आज भी प्रासंगिक है। आप भी कर सकते हैं:

import dateutil
import pytz

date = dateutil.parser.parse('02/11/2019').replace(tzinfo=pytz.UTC)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.