Rem*_*emi 12 python datetime sqlalchemy
我在created_date使用 SQLAlchemy 2.0 和 ORM 模型来获取专栏时遇到了一些真正的麻烦。到目前为止,我找到的最佳答案是在这个评论中:/sf/answers/2347250811/,但是我还无法使该功能正常工作。在我的(简化的)models.py文件中,我有:
import datetime\nfrom sqlalchemy import Integer, String, DateTime\nfrom sqlalchemy.sql import func\nfrom sqlalchemy.orm import DeclarativeBase\nfrom sqlalchemy.orm import Mapped\nfrom sqlalchemy.orm import mapped_column\n\nclass Base(DeclarativeBase):\n pass\n\nclass MyTable(Base):\n __tablename__ = "my_table"\n id: Mapped[int] = mapped_column(primary_key=True)\n name: Mapped[str] = mapped_column(String, nullable=False)\n created_date: Mapped[datetime.datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())\nRun Code Online (Sandbox Code Playgroud)\n到目前为止,一切都很好,我想。在简化版中,engine.py我有:
from sqlalchemy import create_engine\nfrom sqlalchemy import select\nfrom sqlalchemy.orm import Session\n\nimport models\n\ndef add_entry(engine, name_str):\n this_row = models.MyTable()\n this_row.name = name_str\n with Session(engine) as session:\n session.add(this_row)\n session.commit()\nRun Code Online (Sandbox Code Playgroud)\n如果我理解正确的话, 的默认值是created_date一个 SQL 函数,并且 SQLAlchemy 映射now()到 SQLite3 的datetime()。将引擎设置为echo=True,当它尝试运行此插入命令时,我得到以下结果(请注意,这是来自非简化形式的数据,但它仍然非常简单,有 3 个字符串而不是我描述的字符串)
2023-02-06 09:47:07,080 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n2023-02-06 09:47:07,080 INFO sqlalchemy.engine.Engine INSERT INTO coaches (d_name, bb2_name, bb3_name) VALUES (?, ?, ?) RETURNING id, created_date\n2023-02-06 09:47:07,081 INFO sqlalchemy.engine.Engine [generated in 0.00016s] (\'andy#1111\', \'AndyAnderson\', \'Killer Andy\')\n2023-02-06 09:47:07,081 INFO sqlalchemy.engine.Engine ROLLBACK\nRun Code Online (Sandbox Code Playgroud)\n当到达时间函数时,这会导致异常:IntegrityError: NOT NULL constraint failed: coaches.created_date
一些额外的数据(我一直在使用rich产生大量调试信息的库,所以我试图获得最好的部分:
\xe2\x94\x82 \xe2\x95\xad\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 locals \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x95\xae \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82 exc_tb = <traceback object at 0x00000108BD2565C0> \xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82 exc_type = <class \'sqlalchemy.exc.IntegrityError\'> \xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82 exc_value = IntegrityError(\'(sqlite3.IntegrityError) NOT NULL constraint failed: \xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82 coaches.created_date\') \xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82 self = <sqlalchemy.util.langhelpers.safe_reraise object at 0x00000108BD1B79A0> \xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82 traceback = None \xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82 type_ = None \xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82 value = None \xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x82 \xe2\x95\xb0\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x95\xaf\nRun Code Online (Sandbox Code Playgroud)\n无论如何,我觉得在让表列通过调用自动执行 SQL 命令的过程中我已经搞错了func。对这个有什么想法吗?我在 SQLAlchemy 2.0 文档中没有找到任何直接的示例,除了对类似问题的非常棒的评论之外,我还没有找到任何可行的解决方案。
感谢您考虑!
\n我实现了一个 SQLAlchemy 2.0 映射列,其 server_default 为 func.now(),期望该列在 INSERT 操作期间自动填充。在插入操作期间,SQLAlchemy 抛出异常,声称违反了列 NOT NULLABLE 约束 - 因此它不会自动填充。
\n发布我自己的问题的答案,以说明实际的工作原理(实际问题仍然存在,但简化的变体确实按照我期望的方式工作。)
import datetime
from sqlalchemy import Integer, String, DateTime
from sqlalchemy import create_engine
from sqlalchemy.sql import func
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import Session
class Base(DeclarativeBase):
pass
class MyTable(Base):
__tablename__ = "my_table"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String)
created_date: Mapped[datetime.datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)
def initialize_engine(filename):
return create_engine(f"sqlite+pysqlite:///{filename}", echo=True)
def initialize_tables(engine):
Base.metadata.create_all(engine)
def add_row(engine, name):
this_row = MyTable(name=name)
print(this_row)
with Session(engine) as session:
session.add(this_row)
session.commit()
my_file = "test.db"
my_engine = initialize_engine(my_file)
initialize_tables(my_engine)
add_row(my_engine, "Dave")
Run Code Online (Sandbox Code Playgroud)
这会产生结果:
python datetest.py
2023-02-06 11:02:41,157 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-02-06 11:02:41,158 INFO sqlalchemy.engine.Engine PRAGMA main.table_info("my_table")
2023-02-06 11:02:41,158 INFO sqlalchemy.engine.Engine [raw sql] ()
2023-02-06 11:02:41,158 INFO sqlalchemy.engine.Engine COMMIT
<__main__.MyTable object at 0x000002CC767ECD50>
2023-02-06 11:02:41,159 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-02-06 11:02:41,160 INFO sqlalchemy.engine.Engine INSERT INTO my_table (name) VALUES (?) RETURNING id, created_date
2023-02-06 11:02:41,160 INFO sqlalchemy.engine.Engine [generated in 0.00020s] ('Dave',)
2023-02-06 11:02:41,171 INFO sqlalchemy.engine.Engine COMMIT
Run Code Online (Sandbox Code Playgroud)
正确工作的数据库中的架构如下:
sqlite> .schema my_table
CREATE TABLE my_table (
id INTEGER NOT NULL,
name VARCHAR NOT NULL,
created_date DATETIME DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)
所以...我所要做的就是弄清楚为什么我的原始代码没有进行简单的变化!
| 归档时间: |
|
| 查看次数: |
12281 次 |
| 最近记录: |