SQLAlchemy डिफ़ॉल्ट दिनांक समय


174

यह मेरा घोषणात्मक मॉडल है:

import datetime
from sqlalchemy import Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Test(Base):
    __tablename__ = 'test'

    id = Column(Integer, primary_key=True)
    created_date = DateTime(default=datetime.datetime.utcnow)

हालाँकि, जब मैं इस मॉड्यूल को आयात करने का प्रयास करता हूं, तो मुझे यह त्रुटि मिलती है:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "orm/models2.py", line 37, in <module>
    class Test(Base):
  File "orm/models2.py", line 41, in Test
    created_date = sqlalchemy.DateTime(default=datetime.datetime.utcnow)
TypeError: __init__() got an unexpected keyword argument 'default'

यदि मैं एक इंटेगर प्रकार का उपयोग करता हूं, तो मैं एक डिफ़ॉल्ट मान सेट कर सकता हूं। क्या चल रहा है?


1
इसका उपयोग नहीं किया जाना चाहिए। यूटीसी टाइमज़ोन में utcnow एक भोली टाइमस्टैम्प है, हालांकि, संभावना है कि स्थानीय टाइमज़ोन में इसके बजाय भोले टाइमस्टैम्प की व्याख्या की जाती है।
अंती हापाला

1
मुझे पता है कि यह प्रश्न बहुत समय पहले पूछा गया था, लेकिन मुझे लगता है कि आपके उत्तर को उसी में बदल दिया जाना चाहिए जो @Jeff Widman द्वारा प्रदान किया गया हो, क्योंकि दूसरा "रेकॉर्ड" टाइम डेटाइम का उपयोग करेगा जब रिकॉर्ड बनाया जाता है। यदि आप AFK हैं तो कम से कम यह टिप्पणी दूसरों को प्रत्येक प्रश्न के लिए टिप्पणियों की सावधानीपूर्वक जाँच करने की चेतावनी प्रदान करेगी।
डेविड

जवाबों:


186

DateTimeइनपुट के रूप में डिफ़ॉल्ट कुंजी नहीं है। डिफ़ॉल्ट कुंजी Columnफ़ंक्शन के लिए एक इनपुट होनी चाहिए । इसे इस्तेमाल करे:

import datetime
from sqlalchemy import Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Test(Base):
    __tablename__ = 'test'

    id = Column(Integer, primary_key=True)
    created_date = Column(DateTime, default=datetime.datetime.utcnow)

13
यह सही नहीं है। मॉडल लोड पर टाइमस्टैम्प का उपयोग रिकॉर्ड जोड़ने के समय के बजाय सभी नए रिकॉर्ड के लिए किया जाएगा।
स्काईलच

8
@SkyLeach यह कोड सही है, आप इसे यहाँ परीक्षण कर सकते हैं: pastebin.com/VLyWktUndatetime.datetime.utcnowकॉलबैक के रूप में कहा जाता है।
बक्स

1
मैंने इस उत्तर का उपयोग किया लेकिन सभी नए रिकॉर्ड के लिए मॉडल लोड पर टाइमस्टैम्प का उपयोग किया जा रहा है।
स्कूटीडेल्टा

105
@scottdelta: सुनिश्चित करें कि आप उपयोग नहीं कर रहे हैं default=datetime.datetime.utcnow(); आप utcnowफ़ंक्शन को पास करना चाहते हैं , न कि मॉड्यूल लोड पर इसका मूल्यांकन करने का।
शिथिलता

फिर भी मेरे लिए काम नहीं किया। जेफ-विडमैन के दृष्टिकोण ने मेरे लिए काम किया:from sqlalchemy.sql import func; created_date = Column(DateTime(timezone=True), server_default=func.now()
थरंड

396

अपने डीबी के भीतर टाइमस्टैम्प की गणना करें, न कि आपके ग्राहक की

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

SQLAlchemy आपको इसे पारित करने की अनुमति देता है func.now()या func.current_timestamp()(वे एक दूसरे के उपनाम हैं) जो DB को टाइमस्टैम्प की गणना करने के लिए कहता है।

SQLALchemy का प्रयोग करें server_default

इसके अतिरिक्त, एक डिफ़ॉल्ट के लिए जहां आप पहले से ही डीबी को मूल्य की गणना करने के लिए कह रहे हैं, आमतौर पर server_defaultइसके बजाय इसका उपयोग करना बेहतर होता है default। यह SQLAlchemy को CREATE TABLEकथन के भाग के रूप में डिफ़ॉल्ट मान देने के लिए कहता है ।

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

SQLAlchemy onupdate/ को समझनाserver_onupdate

SQLAlchemy भी समर्थन करता है onupdateताकि कभी भी पंक्ति को अपडेट किया जाए यह एक नया टाइमस्टैम्प सम्मिलित करता है। फिर से, डीबी को खुद टाइमस्टैम्प की गणना करने के लिए कहना सबसे अच्छा है:

from sqlalchemy.sql import func

time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())

एक server_onupdateपैरामीटर है, लेकिन इसके विपरीत server_default, यह वास्तव में कुछ भी सर्वराइड सेट नहीं करता है। यह सिर्फ SQLalchemy को बताता है कि अपडेट होने पर आपका डेटाबेस कॉलम को बदल देगा (शायद आपने कॉलम पर ट्रिगर बनाया है ), इसलिए SQLAlchemy रिटर्न वैल्यू मांगेगा ताकि यह संबंधित ऑब्जेक्ट को अपडेट कर सके।

एक अन्य संभावित गोटचा:

आपको यह जानकर आश्चर्य हो सकता है कि यदि आप किसी एकल लेन-देन में परिवर्तन करते हैं, तो वे सभी समान टाइमस्टैम्प रखते हैं। ऐसा इसलिए है क्योंकि SQL मानक निर्दिष्ट करता है कि CURRENT_TIMESTAMPलेनदेन की शुरुआत के आधार पर मान लौटाता है।

PostgreSQL गैर-SQL- मानक प्रदान करता है statement_timestamp()और clock_timestamp()जो एक लेन-देन के भीतर परिवर्तन करते हैं। डॉक्स यहां: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT

UTC टाइमस्टैम्प

यदि आप UTC टाइमस्टैम्प का उपयोग करना चाहते हैं, तो SQLAlchemy प्रलेखनfunc.utcnow() में कार्यान्वयन का एक स्टब प्रदान किया जाता है । आपको अपने दम पर उपयुक्त ड्राइवर-विशिष्ट फ़ंक्शन प्रदान करने की आवश्यकता है।


1
मैंने देखा कि वर्तमान समय का उपयोग करने के लिए पोस्टग्रेज को बताने का एक तरीका है, न कि केवल लेनदेन शुरू करने का समय ... यह पोस्टग्रेज डॉक्स में है
जेफ विडमैन

2
वहाँ एक func.utcnow () या ऐसा कुछ है?
येरेस्सिल

1
@ जेफेविडमैन: क्या हमारे पास उत्कल के लिए एक mysql कार्यान्वयन है? मैं प्रलेखन में केवल mssql और पोस्टग्राउंड
जावा 13

1
यह, वास्तव में, एक महान जवाब है!
जॉन मुतुमा

3
server_default=func.now()मेरे लिए काम किया, लेकिन onupdate=func.now()नहीं किया। कोशिश की onupdate=datetime.datetime.utcnow(कोष्ठक के बिना), वह भी मदद नहीं की
विकास प्रसाद

55

आप डिफ़ॉल्ट के लिए sqlalchemy अंतर्निहित फ़ंक्शन का उपयोग भी कर सकते हैं DateTime

from sqlalchemy.sql import func

DT = Column(DateTime(timezone=True), default=func.now())

9
आप डेटाबेस द्वारा खुद को संभाले हुए मूल्य के server_defaultबजाय उपयोग कर सकते हैं default
rgtk

2
डिस्क्रिप्टर को परिभाषित किए जाने पर func.now () निष्पादित नहीं किया जाता है, इसलिए सभी मॉडल / बच्चे (यदि यह एक आधार वर्ग है) का डीटी मूल्य समान होगा। 'Datetime.datetime.utcnow' जैसे फ़ंक्शन संदर्भ में पास करके, इसे प्रत्येक के लिए अलग से निष्पादित किया जाता है। यह 'निर्मित' या 'अद्यतन' गुणों के लिए महत्वपूर्ण है।
मेटलस्टॉर्म

10
@ मेटालस्टॉर्म नहीं, यह सही है। sqlalchemy.sql.func एक विशेष मामला है जो sqlalchemy.sql.functions.now उदाहरण देता है, वर्तमान समय में नहीं। docs.sqlalchemy.org/en/latest/core/…
क्रिश हार्डी

क्या करता timezone=Trueहै?
चैमग

1
@ से , प्रलेखन से : "यदि यह सच है, और बैकएंड द्वारा समर्थित है, तो ' टाइमस्टेम विद TZZONE ' का उत्पादन करेगा। ऐसे बैकेंड के लिए जो
टाइमज़ोन

7

आप संभवतः उपयोग करना चाहते हैं onupdate=datetime.nowताकि UPDATEs last_updatedफ़ील्ड भी बदल सकें ।

SQLAlchemy में अजगर निष्पादित कार्यों के लिए दो चूक हैं।

  • default INSERT पर मान सेट करता है, केवल एक बार
  • onupdateUPDATE पर कॉल करने योग्य परिणाम के लिए मान सेट करता है ।

मुझे पता नहीं क्यों, लेकिन किसी कारण से onupdateमेरे लिए कुछ नहीं करता है।
विकास प्रसाद

1
: मैं अंत में यह ऐसा करके Postgres डाटाबेस पर काम मिल गया created_at = db.Column(db.DateTime, server_default=UtcNow())और updated_at = db.Column(db.DateTime, server_default=UtcNow(), onupdate=UtcNow())जहां UtcNowके रूप में एक वर्ग है class UtcNow(expression.FunctionElement): type = DateTime()और हमारे पास@compiles(UtcNow, 'postgresql') def pg_utc_now(element, compiler, **kw): return "TIMEZONE('utc', CURRENT_TIMESTAMP)"
विकास प्रसाद

6

defaultकीवर्ड पैरामीटर स्तंभ वस्तु को दी जानी चाहिए।

उदाहरण:

Column(u'timestamp', TIMESTAMP(timezone=True), primary_key=False, nullable=False, default=time_now),

डिफ़ॉल्ट मान एक कॉल करने योग्य हो सकता है, जिसे यहां मैंने निम्नलिखित की तरह परिभाषित किया है।

from pytz import timezone
from datetime import datetime

UTC = timezone('UTC')

def time_now():
    return datetime.now(UTC)

कहाँ time_nowसे आता है?
- एसई बुराई है

धन्यवाद! मैंने मान लिया कि उस नाम के साथ एक अंतर्निहित फ़ंक्शन है जिसे मैंने किसी भी तरह से अनदेखा कर दिया था।
- एसई बुराई है

याdatetime.datetime.utcnow
सर्केफ

1

PostgreSQL प्रलेखन के अनुसार, https://www.postgresql.org/docs/9.6/static/functions-datetime.html

now, CURRENT_TIMESTAMP, LOCALTIMESTAMP return the time of transaction.

इसे एक विशेषता माना जाता है: इरादा एक एकल लेनदेन को "वर्तमान" समय की सुसंगत धारणा रखने की अनुमति देता है, ताकि एक ही लेनदेन के भीतर कई संशोधनों में एक ही समय की मुहर लगे।

यदि आप लेनदेन टाइमस्टैम्प नहीं चाहते हैं तो आप statement_timestamp या clock_timestamp का उपयोग करना चाह सकते हैं ।

statement_timestamp ()

वर्तमान कथन का प्रारंभ समय (अधिक विशेष रूप से, क्लाइंट से नवीनतम कमांड संदेश की प्राप्ति का समय) देता है। statement_timestamp

clock_timestamp ()

वास्तविक वर्तमान समय लौटाता है, और इसलिए एकल SQL कमांड में भी इसका मूल्य बदल जाता है।

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