これは私の宣言モデルです:
import datetime
from sqlalchemy import Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Test(Base):
__table= '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'
整数型を使用する場合、デフォルト値を設定できます。どうしたの?
DateTime
には、入力としてデフォルトキーがありません。デフォルトのキーは、Column
関数への入力でなければなりません。これを試して:
import datetime
from sqlalchemy import Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Test(Base):
__table= 'test'
id = Column(Integer, primary_key=True)
created_date = Column(DateTime, default=datetime.datetime.utcnow)
正気のために、おそらくすべてのdatetimes
を、アプリケーションサーバーではなく、DBサーバーによって計算する必要があります。アプリケーションでタイムスタンプを計算すると、ネットワークレイテンシが変化し、クライアントで発生するクロックドリフトがわずかに異なり、プログラミング言語によって時間の計算が少し異なるため、問題が発生する可能性があります。
SQLAlchemyでは、 func.now()
または func.current_timestamp()
(これらは互いにエイリアスである)を渡すことでこれを行うことができます。タイムスタンプ自体を計算するDB。
server_default
を使用さらに、既に値を計算するようにDBに指示しているデフォルトの場合は、通常、default
の代わりに server_default
を使用することをお勧めします。これにより、SQLAlchemyはCREATE TABLE
ステートメントの一部としてデフォルト値を渡すようになります。
たとえば、このテーブルに対してアドホックスクリプトを記述する場合、server_default
を使用すると、手動でスクリプトにタイムスタンプコールを追加する必要がなくなります。データベースによって自動的に設定されます。
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に伝えるだけです(おそらく、列に triggerを作成した/ )。したがって、SQLAlchemyは戻り値を要求します対応するオブジェクトを更新できます。
驚いたかもしれませんが、1つのトランザクション内で多数の変更を加えた場合、それらはすべて同じタイムスタンプを持ちます。これは、SQL標準がCURRENT_TIMESTAMP
がトランザクションの開始に基づいて値を返すことを指定しているためです。
PostgreSQLは、トランザクション内でdoを変更する非SQL標準のstatement_timestamp()
およびclock_timestamp()
を提供します。ここのドキュメント: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT
UTCタイムスタンプを使用する場合は、func.utcnow()
の実装のスタブが SQLAlchemy documentation で提供されます。ただし、適切なドライバ固有の機能を自分で提供する必要があります。
デフォルトのDateTime
にsqlalchemy組み込み関数を使用することもできます
from sqlalchemy.sql import func
DT = Column(DateTime(timezone=True), default=func.now())
default
キーワードパラメータをColumnオブジェクトに指定する必要があります。
例:
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)
[ここにリンクの説明を入力してください] [1]
おそらくonupdate = datetime.nowを使用して、UPDATEがlast_updatedフィールドも変更するようにします。
[1]:SQLAlchemyには、python実行関数の2つのデフォルトがあります。
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コマンド内でも変化します。