SQLAlchemy 기본 DateTime


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는 UTC 시간대의 순진한 타임 스탬프이지만 순진한 타임 스탬프가 현지 시간대로 해석 될 가능성이 있습니다.
Antti Haapala

1
나는이 질문이 오래 전에 요청되었다는 것을 알고 있지만 @Jeff Widman이 제공 한 답변으로 변경해야한다고 생각합니다. 다른 하나는 테이블 클래스가 정의 될 때와 레코드가 생성 될 때 "컴파일"시간 날짜 시간을 사용하기 때문입니다. AFK 인 경우 최소한이 의견은 다른 사람이 각 질문에 대한 의견을주의 깊게 확인하도록 경고합니다.
David

답변:


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
이것은 옳지 않습니다. 모델로드시 타임 스탬프는 레코드가 추가 된 시간이 아닌 모든 새 레코드에 사용됩니다.
SkyLeach

8
@SkyLeach이 코드는 정확합니다. pastebin.com/VLyWktUn에서 테스트 할 수 있습니다 . datetime.datetime.utcnow콜백이라고합니다.
bux

1
이 답변을 사용했지만 모델로드시 타임 스탬프가 모든 새 레코드에 사용되고 있습니다.
scottydelta 2012 년

105
@scottdelta : 사용하고 있지 않은지 확인하십시오 default=datetime.datetime.utcnow(); utcnow모듈로드에서 함수를 평가 한 결과가 아니라 함수 를 전달하려고합니다 .
기능 장애

여전히 나를 위해 일하지 않았다. jeff-widman의 접근 방식이 나를 위해 일했습니다.from sqlalchemy.sql import func; created_date = Column(DateTime(timezone=True), server_default=func.now()
tharndt

396

클라이언트가 아닌 DB 내 타임 스탬프 계산

건강을 위해 아마도 datetimes응용 프로그램 서버가 아닌 DB 서버에서 모두 계산 해야 할 것입니다 . 응용 프로그램에서 타임 스탬프를 계산하면 네트워크 대기 시간이 가변적이고 클라이언트가 약간 다른 클럭 드리프트를 경험하며 프로그래밍 언어에 따라 시간이 약간 다르게 계산되므로 문제가 발생할 수 있습니다.

SQLAlchemy를 사용하면 타임 스탬프 자체를 계산하도록 DB에 지시 하는 func.now()또는 func.current_timestamp()서로 별칭을 전달하여이 작업을 수행 할 수 있습니다 .

SQLALchemy 사용 server_default

또한 DB에 이미 값을 계산하도록 지시하는 기본값의 경우 일반적으로 server_default대신 대신 사용하는 것이 좋습니다 default. 이것은 SQLAlchemy에게 CREATE TABLE명령문의 일부로 기본값을 전달하도록 지시 합니다.

예를 들어이 표에 대해 임시 스크립트를 작성하는 경우을 사용하면 스크립트에 server_default타임 스탬프 호출을 수동으로 추가하는 것에 대해 걱정할 필요가 없습니다. 데이터베이스가 자동으로 설정합니다.

SQLAlchemy의 이해 onupdate/server_onupdate

또한 SQLAlchemy는 onupdate행이 업데이트 될 때마다 새로운 타임 스탬프를 삽입 할 수 있도록 지원합니다 . 다시 한 번, 타임 스탬프 자체를 계산하도록 DB에 알리는 것이 가장 좋습니다.

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 documentation 에 구현 스텁 func.utcnow()이 제공됩니다 . 그래도 적절한 드라이버 별 기능을 제공해야합니다.


1
트랜잭션 시작 시간뿐만 아니라 Postgres에 현재 시간을 사용하도록 지시하는 방법이 있다는 것을 알았습니다 ... postgres 문서에 있습니다
Jeff Widman

2
func.utcnow () 또는 이와 비슷한 것이 있습니까?
yerassyl

1
@ JeffWidman : utcnow에 대한 mysql 구현이 있습니까? 문서에 난 단지 MSSQL과 postreg
JavaSa

1
이것은 실제로 큰 대답입니다!
존 무투 마

3
server_default=func.now()나를 위해 일했지만 onupdate=func.now()하지 않았다. onupdate=datetime.datetime.utcnow도움이되지 않은 (괄호없이) 시도
Vikas Prasad

55

sqlalchemy 내장 함수를 기본값으로 사용할 수도 있습니다 DateTime

from sqlalchemy.sql import func

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

9
데이터베이스 자체에서 처리하여 가치를 server_default대신 사용할 수도 있습니다 default.
rgtk

2
설명자가 정의 될 때 func.now ()가 실행되지 않으므로 모든 모델 / 자식 (기본 클래스 인 경우)은 동일한 DT 값을 갖습니다. 'datetime.datetime.utcnow'와 같은 함수 참조를 전달하면 각각에 대해 개별적으로 실행됩니다. 이것은 '만들기'또는 '업데이트 된'속성에 중요합니다.
Metalstorm

10
@Metalstorm 아니오, 맞습니다. sqlalchemy.sql.func는 현재 시간이 아니라 sqlalchemy.sql.functions.now 인스턴스를 반환하는 특수한 경우입니다. docs.sqlalchemy.org/en/latest/core/…
Kris Hardy

무엇을 timezone=True합니까?
ChaimG

1
@self, 문서에서 : "참이면 백엔드에서 지원하면 'TIMESTAMP WITH TIMEZONE'이 생성됩니다. 시간대 인식 타임 스탬프를 지원하지 않는 백엔드의 경우 효과가 없습니다 .
ChaimG

7

onupdate=datetime.nowUPDATE가 last_updated필드를 변경 하도록 사용하고 싶을 수도 있습니다 .

SQLAlchemy에는 파이썬 실행 함수에 대한 두 가지 기본값이 있습니다.

  • default INSERT에 값을 한 번만 설정합니다.
  • onupdateUPDATE시에도 호출 가능한 결과로 값을 설정합니다 .

왜 그런지 모르겠지만 어떤 이유로 든 onupdate나를 위해 아무것도하지 않습니다.
Vikas Prasad

1
나는 마침내 이것을 수행함으로써 Postgres db에서 작업하게했습니다 : created_at = db.Column(db.DateTime, server_default=UtcNow())그리고 클래스는 updated_at = db.Column(db.DateTime, server_default=UtcNow(), onupdate=UtcNow())어디에 있고 우리는UtcNowclass UtcNow(expression.FunctionElement): type = DateTime()@compiles(UtcNow, 'postgresql') def pg_utc_now(element, compiler, **kw): return "TIMEZONE('utc', CURRENT_TIMESTAMP)"
Vikas Prasad

6

그만큼 default키워드 매개 변수는 열 개체에 부여해야합니다.

예:

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

기본값은 callable 일 수 있으며 여기서는 다음과 같이 정의했습니다.

from pytz import timezone
from datetime import datetime

UTC = timezone('UTC')

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

어디 time_now에서 왔습니까?
kay-SE는 악하다

감사합니다! 나는 어떻게 든 간과했던 그 이름을 가진 내장 함수가 있다고 가정했습니다.
kay-SE는 사악하다

또는datetime.datetime.utcnow
serkef

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 명령 내에서도 값이 변경됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.