Flask sqlalchemy,在这种情况下如何避免循环依赖



我已经连续两天在思考这个问题了,我仍然可以理解/找到一种方法来做到这一点,它看起来超级简单,但我显然忽略了一些东西(我对数据库管理员来说也很陌生:((。

我想有主人和宠物模型。宠物有"主人ID"作为外键,主人有"宠物"作为关系,到目前为止还不错。但现在我也希望主人有一个"宠物id"写为"最喜欢的宠物"。在两个模型中都有外键(每个模型都有外键(开始产生一堆不同的问题(不同的问题取决于我试图解决它的方式,但要么是循环依赖性,要么是一些多路径错误(

我还注意到,如果我避免在所有者模型中使用"preferente_pet_id"-外键,只保留preferente_pret-relationship,那么我在DB中的任何地方都没有写这个(至少不可见(,它只作为"relationship"存在?

做这件事的正确方法是什么?提前感谢!

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Owner(db.Model):
id = db.Column(db.Integer, primary_key=True)
pets = db.relationship('Pet', foreign_keys='Pet.owner_id')
favourite_id = db.Column(db.Integer, db.ForeignKey('pet.id'))
favourite = db.relationship('Pet', uselist=False, foreign_keys='Owner.favourite_id')
class Pet(db.Model):
id =db.Column(db.Integer, primary_key=True)
owner_id = db.Column(db.Integer, db.ForeignKey('owner.id'))
owner = db.relationship('Owner', uselist=False, back_populates='pets', foreign_keys='Pet.owner_id')

o = Owner()  # one owner
p1 = Pet()   # pet 1
p2 = Pet()   # pet 2
p1.owner=o   # setting owner for pet1
p2.owner=o   # setting owner for pet2
o.favourite=p2  # setting pet2 to be favourite
#db.session.add(o)
#db.session.add(p1)
#db.session.add(p2)
#db.session.commit()
print (p1.owner) # owner
print (p2.owner) # owner
print (p1) # pet 1
print (p2) # pet 2
print (o.pets) # owners pets
print (o.favourite) # favourite pet

下面是您的代码的工作版本。关键是对关系(例如联接条件(更加明确,因为模型/表之间存在多个关系。

注意:虽然不是你的问题/请求的一部分,但我也重新格式化了一些PEP8的一致性和可读性。后者是早期采用的一种好做法,因为模型文件通常增长很快,并且可能变得很难读取、消化和调试。

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Owner(db.Model):
id = db.Column(
db.Integer,
primary_key=True,
)
favourite_pet_id = db.Column(
db.Integer,
db.ForeignKey('pet.id'),
nullable=True,
)
favourite_pet = db.relationship(
'Pet',
uselist=False,
foreign_keys=[favourite_pet_id],
primaryjoin='Pet.owner_id == Owner.favourite_pet_id',
)

class Pet(db.Model):
id = db.Column(
db.Integer,
primary_key=True,
)
owner_id = db.Column(
db.Integer,
db.ForeignKey('owner.id'),
)
owner = db.relationship(
'Owner',
uselist=False,
foreign_keys=[owner_id],
primaryjoin='Pet.owner_id == Owner.id',
backref=db.backref(
'pets',
uselist=True,
),
)

db.create_all()
o = Owner()  # one owner
p1 = Pet()  # pet 1
p2 = Pet()  # pet 2
p1.owner = o  # setting owner for pet1
p2.owner = o  # setting owner for pet2
o.favourite_pet = p2  # setting pet2 to be favourite
print(p1.owner)  # owner
print(p2.owner)  # owner
print(p1)  # pet 1
print(p2)  # pet 2
print(o.pets)  # owners pets
print(o.favourite)  # favourite pet

最新更新