无法在flask-sqlalchemy中创建自引用外键

时间:2013-12-29 21:15:10

标签: python sqlalchemy flask flask-sqlalchemy

我有一个模型Region,每个Region都可以有子区域。每个子区域都有一个字段parent_id,它是其父区域的id。这是我的模型的样子

class Region(db.Model):
    __tablename__ = 'regions'
    __table_args__ = {'schema': 'schema_name'}
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))
    parent_id = db.Column(db.Integer, db.ForeignKey('regions.id'))
    parent = db.relationship('Region', primaryjoin=('Region.parent_id==Region.id'), backref='sub-regions')
    created_at = db.Column(db.DateTime, default=db.func.now())
    deleted_at = db.Column(db.DateTime)

当我尝试db.create_all时,我收到此错误sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'regions.parent_id' could not find table 'regions' with which to generate a foreign key to target column 'id'

为什么我在regions中指定__tablename__时找不到__table_args__ = {'schema': 'schema_name'} ?我正在使用flask-sqlalchemy版本1.0

编辑 - 我删除了这行

{{1}}
从我的代码

它的工作原理。打败了我。

4 个答案:

答案 0 :(得分:9)

您必须告诉SQLAlchemy关系的“远程端”是什么,以区分当前行和要连接的行。相关解释位于this section of the documentation关系的中间位置。

这种关系可能如下所示:

parent = db.relationship('Region', remote_side=id, backref='sub_regions')

这是一个展示自我指涉关系的例子:

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative.api import declarative_base
from sqlalchemy.orm import sessionmaker, relationship

engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(engine)
Base = declarative_base(engine)

session = Session()


class Region(Base):
    __tablename__ = 'region'

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    parent_id = Column(Integer, ForeignKey('region.id'), index=True)

    parent = relationship(lambda: Region, remote_side=id, backref='sub_regions')


Base.metadata.create_all()

r1 = Region(name='United States of America')
r2 = Region(name='California', parent=r1)

session.add_all((r1, r2))
session.commit()

ca = session.query(Region).filter_by(name='California').first()
print ca.parent.name

自启用echo以来,SQL输出会有很多行,脚本最后会打印“美利坚合众国”。

答案 1 :(得分:2)

我对模式名称参数有同样的问题。我改变它的工作原理是直接在ForeignKey和关系中引用表类而不是使用字符串。 例如:

parent_id = Column(Integer, ForeignKey(Region.id), index=True)

parent = relationship(lambda: Region, remote_side=id, backref='sub_regions')

答案 2 :(得分:0)

我只看到与@davidism的细微差别,但这对我来说直接在SQLAlchemy中起作用。

from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.orm import backref

class Region(Base):
  __tablename__ = 'region'

  id = Column(Integer, primary_key=True)
  parent_id = Column(Integer, ForeignKey('region.id'), index=True)
  sub_regions = relationship('Region', backref=backref('parent', remote_side='Region.id'))

正如他指出的那样,我猜测你不需要导入,但应该在db前加上它们,如下所示:

class Region(db.Model):
  __tablename__ = 'region'

  id = db.Column(db.Integer, primary_key=True)
  parent_id = db.Column(db.Integer, db.ForeignKey('region.id'), index=True)
  sub_regions = db.relationship('Region', backref=db.backref('parent', remote_side='Region.id'))

答案 3 :(得分:0)

如果对任何表使用模式,则具有引用这些模式表的外键的其他表必须提供模式的名称。见the docs here

class Table(db.Model):
    __tablename__ = 'table_1_name'
    __table_args__ = {'schema': 'my_schema'}

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

class AnotherTable(db.Model):
    __tablename__ = 'table_2_name'
    # Doesn't matter if this belongs to the same or different schema
    # __table_args__ = {'schema': 'my_schema'}

    id = Column('id', Integer, primary_key=True)
    t1_id = Column(Integer, ForeignKey('my_schema.table_1_name.id'))
    ...

适用于SQLAlchemy和Flask-SQLAlchemy。希望这可以帮助。 :d