具有相同反向引用名称的同一个表的多个关系

时间:2019-08-27 14:32:41

标签: python-3.x sqlalchemy flask-sqlalchemy

我正在构建一个项目清单应用程序,其中项目通过某种主项目链接在一起。一个主项目有几个不同的项目。我希望能够从每个项目访问相应的主项目。一个项目只能链接到一个主项目。

该应用程序是使用Flask和SQLAlchemy以及Python 3.6.5构建的。我尝试了几种back_refback_populates的技巧,但总是遇到此错误:

sqlalchemy.exc.ArgumentError: Error creating backref 'projects' on relationship 'MasterProject.reseller_project': property of that name exists on mapper 'Mapper|Project|projects'

我发现了有关该主题的其他几篇文章,但是backref总是引用不同的名称。如果可以的话,我希望使用相同的名称。

这是我的代码:

class Project(db.Model):
    __tablename__ = 'projects'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

class MasterProject(db.Model):
    __tablename__ = 'master_projects'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    manufacturer_pid = db.Column(db.Integer, db.ForeignKey('projects.id'))
    reseller_pid = db.Column(db.Integer, db.ForeignKey('projects.id'))
    distributor_pid = db.Column(db.Integer, db.ForeignKey('projects.id'))
    influencer_pid = db.Column(db.Integer, db.ForeignKey('projects.id'))

    manufacturer_project = db.relationship('Project', foreign_keys=[manufacturer_pid],
                                           backref='master_project')
    reseller_project = db.relationship('Project', foreign_keys=[reseller_pid],
                                       backref='master_project')
    distributor_project = db.relationship('Project', foreign_keys=[distributor_pid],
                                          backref='master_project')
    influencer_project = db.relationship('Project', foreign_keys=[influencer_pid],
                                         backref='master_project')

我想要以下内容:假设p1是一个项目。我希望能够访问p1.master_project,而不管其主项目中的p1是什么。

1 个答案:

答案 0 :(得分:0)

您的示例似乎很适合Class Inheritance Pattern

您有多种从基类Project继承的项目类型,而不是一种项目类型。然后,来自MasterProject的关系backrefs都可以指向该关系表示的适当类。

例如:

class Project(db.Model):
    __tablename__ = "projects"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    type_ = db.Column(db.String(20), nullable=False)

    __mapper_args__ = {"polymorphic_on": type_}


class ResellerProject(Project):

    __mapper_args__ = {"polymorphic_identity": "reseller"}


class ManufacturerProject(Project):

    __mapper_args__ = {"polymorphic_identity": "manufacturer"}


class DistributorProject(Project):

    __mapper_args__ = {"polymorphic_identity": "distributor"}


class InfluencerProject(Project):

    __mapper_args__ = {"polymorphic_identity": "influencer"}


class MasterProject(db.Model):
    __tablename__ = "master_projects"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    manufacturer_pid = db.Column(db.Integer, db.ForeignKey("projects.id"))
    reseller_pid = db.Column(db.Integer, db.ForeignKey("projects.id"))
    distributor_pid = db.Column(db.Integer, db.ForeignKey("projects.id"))
    influencer_pid = db.Column(db.Integer, db.ForeignKey("projects.id"))

    manufacturer_project = db.relationship(
        "ManufacturerProject",
        foreign_keys=[manufacturer_pid],
        backref="master_project",
    )
    reseller_project = db.relationship(
        "ResellerProject",
        foreign_keys=[reseller_pid],
        backref="master_project",
    )
    distributor_project = db.relationship(
        "DistributorProject",
        foreign_keys=[distributor_pid],
        backref="master_project",
    )
    influencer_project = db.relationship(
        "InfluencerProject",
        foreign_keys=[influencer_pid],
        backref="master_project",
    )

在这里,我们仍然只有一个projects表,但是在该表中添加了另一列,以将一种类型的项目与另一种类型的项目区分开。 Project的每个子类都通过"polymorphic_identity"字典中的__mapper_args__键与唯一的标识符相关联。由于每个类型都是单独的类型,因此它们每个都可以具有指向MasterProject的关系。