最近我发现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
命令时使用,它确实让我感到困惑。为什么人们更喜欢default
而不是server_default
?我如何实现我想要的目标?我应该在__init__
中指定所有默认参数吗?这似乎是代码重复:更改默认值我必须将其更改两次并保持这些值相等 - 是否有某种方法可以避免这种情况?
由于以下四个原因之一,人们更喜欢默认优先于服
在这种情况下,当您在应用程序中将“foo”设置为“0”而不依赖于数据库操作时,选项为:
__init__()
。这是蟒蛇!这是__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
您可以使用init
事件填充默认值。这个事件监听器会这样做:
from sqlalchemy import event
from sqlalchemy.orm import mapper
from sqlalchemy.inspection import inspect
def instant_defaults_listener(target, args, kwargs):
for key, column in inspect(target.__class__).columns.items():
if column.default is not None:
if callable(column.default.arg):
setattr(target, key, column.default.arg(target))
else:
setattr(target, key, column.default.arg)
event.listen(mapper, 'init', instant_defaults_listener)
您可以使用force_instant_defaults
中的sqlalchemy_utils
监听器来更改此行为:
from sqlalchemy_utils import force_instant_defaults
force_instant_defaults()
class TestModel(Base):
__tablename__ = 'tmodel'
id = sa.Column(sa.Integer, primary_key=True)
foo = sa.Column(sa.Integer, default=0)
model = TestModel()
assert model.foo == 0