python – 为什么在提交对象之前SQLAlchemy的默认列值不可用?

最近我发现SQLAlchemy的Column的默认值不能像我预期的那样工作:

>>> Base = declarative_base()
>>> class TestModel(Base):
    ...     __tablename__ = 'tmodel'
...     id = sa.Column(sa.Integer, primary_key=True)
...     foo = sa.Column(sa.Integer, default=0)
...    
>>> tmodel_instance = TestModel()
>>> print tmodel_instance.foo
None
>>> session.add(tmodel_instance)
>>> print tmodel_instance.foo
None
>>> session.commit()
>>> print tmodel_instance.foo
0

我想要在对象实例化之后使tmodel_instance.foo等于0,但是似乎默认值仅在执行INSERT命令时使用,这真的让我感到困惑。为什么会喜欢默认超过server_default?而我如何实现我想要的?我应该在__init__中指定所有默认参数吗?这似乎是代码重复:要更改默认值,我必须更改它两次,并保持这些值相等 – 有没有办法避免?

人们更喜欢默认超过服务器默认值,原因如下:

>您希望运行一个Python函数,而不是一个SQL函数,用于默认(或者一个需要一些每个INSERT Python状态的SQL表达式)。
>默认是主键列的一部分。 ORM无法加载没有主键的行,因此在使用ORM时,server_default对于PK列通常不是有用的。
>您要运行的SQL表达式作为“服务器默认值”不被数据库支持。
>你正在处理你不想/不想改变的模式。

在这种情况下,当您在应用程序中“foo”为“0”,与数据库操作无关,其选择如下:

>使用__init __()。这是python!
>使用事件。

这里是__init __():

class TestModel(Base):
   # ...

   def __init__(self):
       self.foo = 0

这是事件(具体是init event):

from sqlalchemy import event

@event.listens_for(Foo, "init")
def init(target, args, kwargs):
    target.foo = 0
翻译自:https://stackoverflow.com/questions/14002631/why-isnt-sqlalchemy-default-column-value-available-before-object-is-committed

转载注明原文:python – 为什么在提交对象之前SQLAlchemy的默认列值不可用?