gpt4 book ai didi

python - 如何防止 Flask/SQLAlchemy 模型中出现这种循环引用?

转载 作者:行者123 更新时间:2023-11-30 22:47:38 26 4
gpt4 key购买 nike

我的 Flask/SQLAlchemy 应用程序中有以下四个模型类(第五个类 MyClassA 此处未显示,但作为引用):

class MyClassF(db.Model):
valid_fs = ['F1', 'F2']
f_id = db.Column(db.Integer, nullable=False, primary_key=True)
name = db.Column(db.Enum(*valid_fs, name='f_enum'), default='F1', nullable=False)

class MyClassD(db.Model):
d_id = db.Column(db.Integer, nullable=False, primary_key=True)
name = db.Column(db.String(128))
v_collection = db.relationship('MyClassV', lazy='dynamic', backref=db.backref('d'), cascade='all, delete-orphan')

class MyClassV(db.Model):
v_id = db.Column(db.Integer, nullable=False, primary_key=True)
d_id = db.Column(db.Integer, db.ForeignKey(MyClassD.d_id), nullable=False)
c_collection = db.relationship('MyClassC', lazy='dynamic', backref=db.backref('v'), cascade='all, delete-orphan')
a_collection = db.relationship('MyClassA', lazy='dynamic', backref=db.backref('v'), cascade='all, delete-orphan')

class MyClassC(db.Model):
c_id = db.Column(db.Integer, nullable=False, primary_key=True)
v_id = db.Column(db.Integer, db.ForeignKey(MyClassV.v_id), nullable=False)
f_id = db.Column(
db.Integer,
db.ForeignKey(MyClassF.f_id),
nullable=False,
#default=MyClassF.query.filter(MyClassF.name == "F1").one().f_id
)

使用 Flask-Migrate 创建此架构命令db initdb migratedb Upgrade工作得很好。

但是,当我取消注释 MyClassC.f_id 的定义行并重试时(删除 migrations 目录后),我得到以下循环依赖项错误:

sqlalchemy.exc.InvalidRequestError: When initializing mapper Mapper|MyClassV|my_classV, expression 'MyClassC' failed to locate a name ("name 'MyClassC' is not defined"). If this is a class name, consider adding this relationship() to the class after both dependent classes have been defined.

我要做的就是确保通过查询MyClassF 表来设置MyClassC.f_id 的默认值。此检查应在插入时进行,而不是在创建数据库时进行。所以我不明白为什么现在会收到此错误。

如何使用db.relationship()(或任何其他技术)来解决此循环依赖错误,同时强制执行我正在尝试实现的数据库完整性规则?

最佳答案

我相信默认参数已转换为 SQL DEFAULT constraint 。 AFAICT 在插入时不会评估此约束,而是在创建表时评估该值,然后将该值用作默认值(这意味着默认值在创建表时一次性设置并用于缺少该列的所有行,它不能根据其他表的内容动态更改)。

但是the documentation of SQLAlchemy提到您可以传入一个 python 函数 作为默认值,并且每次插入都会调用它来获取要使用的默认值,因此您可以这样做:

class MyClassC(db.Model):
c_id = db.Column(db.Integer, nullable=False, primary_key=True)
v_id = db.Column(db.Integer, db.ForeignKey(MyClassV.v_id), nullable=False)
f_id = db.Column(
db.Integer,
db.ForeignKey(MyClassF.f_id),
nullable=False,
default=lambda: MyClassF.query.filter(MyClassF.name == "F1").one().f_id
)

但请注意,这不会使用任何数据库工具来提供默认值,它是 SQLAlchemy 首先获取默认值,然后手动将其插入到查询中。

关于python - 如何防止 Flask/SQLAlchemy 模型中出现这种循环引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40460435/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com