简体   繁体   English

一对多关系| Flask-SQLAlchemy和Flask-Migrate

[英]One to Many Relationship | Flask-SQLAlchemy and Flask-Migrate

Attempting a one-to-many relationship between an outbound email (child), the source (parent 1) and target (parent 2). 尝试在出站电子邮件(子级),源(父级1)和目标(父级2)之间建立一对多关系。 I am attempting to use flask-migrate for the setup of the database. 我正在尝试使用flask-migrate进行数据库设置。 The command I'm using: 我正在使用的命令:

python manage.py db migrate

Getting the following error: 出现以下错误:

sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'outbound_emails.target_id' could not find table 'targets' with which to generate a foreign key to target column 'id'

Here's what I have so far: 这是我到目前为止的内容:

class Contact(Base):
    __abstract__ = True
    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.Text, nullable=False)
    last_name = db.Column(db.Text, nullable=False)
    email = db.Column(db.Text, nullable=False)
    phone = db.Column(db.Text, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow())
    last_activity = db.Column(db.DateTime, default=datetime.utcnow())
    json_data = db.Column(sqlalchemy.dialects.postgresql.JSON)

    def __init__(self, first_name, last_name, email, phone,
                 created_date=datetime.utcnow(), last_activity=datetime.utcnow(), json_data=None):
        if json_data is None:
            json_data = {}
        self.first_name = first_name
        self.last_name = last_name
        self.email = email
        self.phone = phone
        self.created_date = created_date
        self.last_activity = last_activity
        self.json_data = json_data


class Target(Contact):
    __tablename__ = 'targets'
    outbound_emails = db.relationship("OutboundEmail", backref="target", lazy='dynamic')

    @property
    def __repr__(self):
        return '<target_id {}>'.format(self.target_id)


class Source(Contact):
    __tablename__ = 'sources'
    outbound_emails = db.relationship("OutboundEmail", backref="source", lazy='dynamic')

    @property
    def __repr__(self):
        return '<source_id {}>'.format(self.source_id)


class OutboundEmail(db.Model):
    __tablename__ = 'outbound_emails'
    email_id = db.Column(db.Integer, primary_key=True)
    provider_id = db.Column(db.Text, nullable=True)
    source_id = db.Column(db.Integer, db.ForeignKey("sources.id"))
    target_id = db.Column(db.Integer, db.ForeignKey("targets.id"))
    data = db.Column(sqlalchemy.dialects.postgresql.JSON)

    def __init__(self, provider_id, source, target, merge_fields):
        self.provider_id = provider_id
        self.source = source
        self.target = target
        self.data = merge_fields


    @property
    def __repr__(self):
        return '<email_id {}>'.format(self.email_id)

Does anybody see what I'm doing wrong here? 有人看到我在做什么错吗? Thanks! 谢谢!

The solution may depend on which type of inheritance you are trying to achieve, either single table, concrete table or joined table inheritance. 解决方案可能取决于您要实现的继承类型,是单表继承,具体表继承还是联合表继承。

Considering that you have marked your base class as _abstract_ I suppose that you want to map each subclass to its own distinct table, thus using a form of concrete inheritance . 考虑到您已将基类标记为_abstract_我想您想将每个子类映射到其自己的不同表,从而使用一种具体的继承形式。

In that case you need to define all columns explicitly on each subclass, even those of the same name. 在这种情况下,您需要在每个子类上显式定义所有列,即使是相同名称的列也是如此。 So at least you need to set: 因此,至少您需要设置:

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

on your derived classes. 在您的派生类上。

In addition to that, you may also need to set a polymorphic identity in your subclasses, and possibly extend it to allow polymorphic loading. 除此之外,您可能还需要在子类中设置多态标识,并可能对其进行扩展以允许多态加载。 I suggest to take a look at the wonderful SQLAlchemy documentation on this topic. 我建议看一下有关此主题的精彩的SQLAlchemy文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM