Django डेटाटाइम मुद्दे (डिफ़ॉल्ट = datetime.now ())


283

मेरे पास नीचे db मॉडल है:

from datetime import datetime    

class TermPayment(models.Model):
    # I have excluded fields that are irrelevant to the question
    date = models.DateTimeField(default=datetime.now(), blank=True)

मैं नीचे का उपयोग करके एक नया उदाहरण जोड़ता हूं:

tp = TermPayment.objects.create(**kwargs)

मेरा मुद्दा: डेटाबेस में सभी अभिलेखों का दिनांक फ़ील्ड में समान मान है, जो पहले भुगतान की तारीख है। सर्वर के पुनरारंभ होने के बाद, एक रिकॉर्ड में नई तारीख होती है और अन्य रिकॉर्ड पहले की तरह ही होते हैं। ऐसा लगता है जैसे कुछ डेटा कैश किया गया है, लेकिन मुझे यह नहीं मिल रहा है।

डेटाबेस: mysql 5.1.25

django v1.1.1


1
इस तरह के एक समारोह के लिए डिफ़ॉल्ट रूप से संभव नहीं है ?: default=datetime.now- नोट, now()DateTimeField के लिए नहीं मानक के रूप में फोन के बिना , लेकिन ... आसान anycase।
viridis

जवाबों:


597

ऐसा लगता datetime.now()है कि मॉडल के परिभाषित होने पर मूल्यांकन किया जा रहा है, न कि हर बार जब आप रिकॉर्ड जोड़ते हैं।

Django में वह सुविधा है जो आप पहले से ही करने की कोशिश कर रहे हैं:

date = models.DateTimeField(auto_now_add=True, blank=True)

या

date = models.DateTimeField(default=datetime.now, blank=True)

दूसरे उदाहरण और आपके पास वर्तमान में जो अंतर है, वह कोष्ठक की कमी है। datetime.nowकोष्ठक के बिना गुजरने से , आप वास्तविक फ़ंक्शन को पारित कर रहे हैं, जिसे हर बार एक रिकॉर्ड जोड़ा जाता है। यदि आप इसे पास करते हैं datetime.now(), तो आप केवल फ़ंक्शन का मूल्यांकन कर रहे हैं और इसे रिटर्न मान दे रहे हैं।

अधिक जानकारी Django के मॉडल फ़ील्ड संदर्भ में उपलब्ध है


206
महत्वपूर्ण सूचना : auto_now_add का उपयोग करने से व्यवस्थापक में संयुक्त राष्ट्र के संपादन योग्य हो जाता है
जियारो

7
शानदार जवाब, धन्यवाद। क्या डेटाइमटाइम के साथ अधिक जटिल अभिव्यक्ति को व्यक्त करने का एक तरीका है। एक डिफ़ॉल्ट के रूप में? उदाहरण के लिए अब + 30 दिन (निम्नलिखित काम नहीं करता है) expiry = models.DateTimeField(default=datetime.now + timedelta(days=30))
मिकेला

26
@michela datetime.now एक फ़ंक्शन है, और आप एक फ़ंक्शन में टाइमडेलटा जोड़ने की कोशिश कर रहे हैं। आपको डिफ़ॉल्ट मान सेट करने के लिए अपने कॉलबैक को परिभाषित करना होगा, जैसे def now_plus_30(): return datetime.now() + timedelta(days = 30), और फिर उपयोग करेंmodels.DateTimeField(default=now_plus_30)
कार्सन मायर्स

55
या आप निश्चित रूप से कर सकते हैंdefault=lambda: datetime.now()+timedelta(days=30)
माइकल Mior

34
BE AWARE कि Auto_now_add का उपयोग करना डिफ़ॉल्ट के रूप में समान नहीं है क्योंकि फ़ील्ड ALWAYS अब (uneditable) के बराबर होगी .. मुझे पता है कि यह पहले से ही कहा गया था, लेकिन यह केवल उस पृष्ठ "व्यवस्थापक" पृष्ठ का एक
मेट्टर नहीं है

115

उपयोग करने के बजाय datetime.nowआपको वास्तव में उपयोग करना चाहिएfrom django.utils.timezone import now

संदर्भ:

इसलिए कुछ इस तरह से जाएं:

from django.utils.timezone import now


created_date = models.DateTimeField(default=now, editable=False)

13
यह एक बहुत ही महत्वपूर्ण नोट है! अगर आप डेटाटाइम का उपयोग करते हैं। तो आप एक स्थानीय डेटाटाइम का उपयोग कर सकते हैं जो टाइमज़ोन के बारे में पता नहीं है। यदि आप बाद में इसकी तुलना एक ऐसे क्षेत्र से करते हैं, auto_now_addजिसका उपयोग करके टाइमस्टैम्प किया गया था (जिसे टाइमज़ोन के बारे में पता है) तो आप समय-समय के अंतर के कारण गलत गणना प्राप्त कर सकते हैं।
इफ्ता

1
यह निश्चित रूप से बहुत महत्वपूर्ण है लेकिन वास्तव में इस सवाल का जवाब खुद से नहीं देता है।
20

1
निश्चित रूप से बेहतर तरीका
कारमाइन टैम्बिशिया

28

Django मॉडल डिफ़ॉल्ट फ़ील्ड पर प्रलेखन से :

फ़ील्ड के लिए डिफ़ॉल्ट मान। यह एक मूल्य या एक कॉल करने योग्य वस्तु हो सकती है। यदि कॉल करने योग्य है तो हर बार एक नई वस्तु बनाई जाएगी।

इसलिए निम्नलिखित काम करना चाहिए:

date = models.DateTimeField(default=datetime.now,blank=True)

1
यह केवल django 1.8+ में
डेविड शूमान

@DavidNathan वह क्यों है? मुझे लगता है कि दोनों विकल्प 1.4 या उससे पहले के आसपास रहे हैं, जिसमें एक कॉल करने योग्यdefault ( django-chinese-docs-14.readthedocs.io/en/latest/ref/models/… ) का उपयोग शामिल है
मार्क

16

डेविड के पास सही जवाब था। कोष्ठक () इसे बनाता है ताकि कॉल करने योग्य timezone.now () मॉडल के मूल्यांकन के लिए हर बार कहा जाता है। यदि आप टाइमज़ोन से निकालते हैं () () (या datetime.now (), यदि भोली डेटाइम ऑब्जेक्ट का उपयोग कर रहे हैं) तो बस इसे बनाने के लिए:

default=timezone.now

फिर यह आपकी अपेक्षा के अनुसार काम करेगा:
नई वस्तुओं को वर्तमान तिथि तब प्राप्त होगी जब वे बनाई जाती हैं, लेकिन हर बार जब आप प्रबंध करें या नहीं करेंगे तो ओवरराइड की अनुमति नहीं होगी।

मैंने अभी इसका सामना किया। डेविड को बहुत धन्यवाद।


10

datetime.now()जब नहीं नया रिकार्ड डेटाबेस में जोड़ा जा रहा है, जब वर्ग बनाई गई है मूल्यांकन किया जाता है,।

आप इस क्षेत्र को किस रूप में परिभाषित करना चाहते हैं, इसे प्राप्त करने के लिए:

date = models.DateTimeField(auto_now_add=True)

इस तरह यह dateक्षेत्र प्रत्येक नए रिकॉर्ड के लिए वर्तमान तिथि पर सेट हो जाएगा।


6

इस एक का जवाब वास्तव में गलत है।

मान में स्वतः भरना (auto_now / auto_now_add डिफ़ॉल्ट के समान नहीं है)। डिफ़ॉल्ट मूल्य वास्तव में वही होगा जो उपयोगकर्ता देखता है कि क्या यह एक नई वस्तु है। मैं आमतौर पर क्या करता हूं:

date = models.DateTimeField(default=datetime.now, editable=False,)

सुनिश्चित करें, यदि आपका व्यवस्थापक पृष्ठ में यह प्रतिनिधित्व करने की कोशिश कर रहा है, कि आप इसे 'read_only' के रूप में सूचीबद्ध करते हैं और फ़ील्ड नाम का संदर्भ देते हैं

read_only = 'date'

जब से मेरा डिफ़ॉल्ट मान आमतौर पर संपादन योग्य नहीं है, तब से मैं ऐसा करता हूं, और जब तक अन्यथा निर्दिष्ट नहीं किया जाता है, तब तक व्यवस्थापक पृष्ठ गैर-संपादन योग्य को अनदेखा करते हैं। हालाँकि डिफ़ॉल्ट मान सेट करने और auto_add को लागू करने के बीच एक अंतर है जो यहाँ कुंजी है। इसका परीक्षण करो!


6

datetime.now()का मूल्यांकन एक बार किया जा रहा है, जब आपकी कक्षा को त्वरित किया जाता है। कोष्ठक को हटाने की कोशिश करें ताकि फ़ंक्शन datetime.nowवापस आ जाए और इसका मूल्यांकन किया जाए। मेरे पास अपने DateTimeFieldएस के लिए डिफ़ॉल्ट मान सेट करने के साथ एक ही मुद्दा था और यहां अपना समाधान लिखा ।


5

समारोह परिभाषा के तहत पायथन भाषा संदर्भ से :

फ़ंक्शन परिभाषा निष्पादित होने पर डिफ़ॉल्ट पैरामीटर मानों का मूल्यांकन किया जाता है। इसका मतलब है कि अभिव्यक्ति का मूल्यांकन एक बार किया जाता है, जब फ़ंक्शन को परिभाषित किया जाता है, और यह कि प्रत्येक कॉल के लिए "पूर्व-गणना" मूल्य का उपयोग किया जाता है।

सौभाग्य से, Django के पास वह तरीका है जो आप चाहते हैं, यदि आप इसके लिए auto_nowतर्क का उपयोग करते हैं DateTimeField:

date = models.DateTimeField(auto_now=True)

DateTimeField के लिए Django डॉक्स देखें ।


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