首页 > 解决方案 > Flask-SQLAlchemy 和第三范式

问题描述

如何实现第 3 范式,例如Address在 Flask-SQLAlchemy 中有一个单独的模型?开玩笑的是,我希望能够从多个不同的模型中使用这个单独的模型。

例如,假设我有两个不同的模型, aPerson和 a Company

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    street_address = db.Column(db.Text, nullable=False)
    postal_code = db.Column(db.Text, nullable=False)
    city = db.Column(db.Text, nullable=False)
    country = db.Column(db.Text, nullable=False)
    # ...and so on

class Company(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    street_address = db.Column(db.Text, nullable=False)
    postal_code = db.Column(db.Text, nullable=False)
    city = db.Column(db.Text, nullable=False)
    country = db.Column(db.Text, nullable=False)
    # ...and so on

现在这只是愚蠢的。地址不取决于它是个人还是公司。所以我可以制作一个单独的模型,如下所示:

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    street_address = db.Column(db.Text, nullable=False)
    postal_code = db.Column(db.Text, nullable=False)
    city = db.Column(db.Text, nullable=False)
    country = db.Column(db.Text, nullable=False)

然后将我的人物模型更改为:

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    address_id = db.Column(db.Integer, db.ForeignKey('address.id'), nullable=False)
    # ...and so on

Address然后添加对我的模型的反向引用:

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    street_address = db.Column(db.Text, nullable=False)
    postal_code = db.Column(db.Text, nullable=False)
    city = db.Column(db.Text, nullable=False)
    country = db.Column(db.Text, nullable=False)
    person = db.relationship('Person', backref='address', lazy=True) # << NEW!

但是,现在我有一个设计可以AddressPerson. 我希望所有可能需要地址的模型都能够使用该模型。我如何实现这一目标?

标签: pythonflaskflask-sqlalchemy

解决方案


您不应该添加relationshipon Address。该表/模型与地址是 aPerson还是 a无关Company

将关系添加到父母:

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    address_id = db.Column(db.Integer, db.ForeignKey('address.id'), nullable=False)
    address = db.relationship(Address)
    # ...and so on

relationship任何范式无关,它是为了协助 ORM 从查询结果创建 Python 对象,并且不会改变数据库的结构。将其添加到地址依赖于backref使属性可用,这是不必要的模糊


推荐阅读