这是我的简单模型
class Record(db.Model):
__tablename__ = 'reg_records'
request_id = db.Column(db.Integer, primary_key = True)
title = db.Column(NVARCHAR())
class Field(db.Model):
__tablename__ = 'reg_fields'
request_id = db.Column(db.Integer, primary_key= True)
name = db.Column(NVARCHAR(), primary_key = True)
现在我想将相关字段映射到记录。我正在遵循flask-sqlalchemy规范并获得此
class Field(db.Model):
__tablename__ = 'reg_fields'
request_id = db.Column(db.Integer, ForeignKey('record.request_id'), primary_key= True)
name = db.Column(NVARCHAR(), primary_key = True)
class Record(db.Model):
__tablename__ = 'reg_records'
request_id = db.Column(db.Integer, primary_key = True)
title = db.Column(NVARCHAR())
fields = db.relationship(Field, backref = 'record')
然而,当我尝试使用此模型时,我收到以下错误
sqlalchemy.exc.NoForeignKeysError
NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Record.fields - there are no foreign keys linking these tables. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.
将primaryjoin
添加到关系声明中,如下所示
fields = db.relationship(Field, backref = 'record', primaryjoin='Record.request_id==Field.request_id')
无法解决问题,而是提供新的异常
sqlalchemy.exc.NoReferencedTableError
NoReferencedTableError: Foreign key associated with column 'reg_fields.request_id' could not find table 'record' with which to generate a foreign key to target column 'request_id'
如果我用primaryjoin值中的表名替换类名,
fields = db.relationship(Field, backref = 'record', primaryjoin='reg_records.request_id==reg_fields.request_id')
我得到另一个异常
sqlalchemy.exc.InvalidRequestError
InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Original exception was: 'Table' object has no attribute 'request_id'
总的来说,在flask-sqlalchemy中建立一对多关系的正确方法是什么。
答案 0 :(得分:4)
目前还不是很清楚你要做什么。我假设您正在尝试在Record和Field之间建立一对多的关系(一个Record可以有零个或多个Fields)。我还假设您希望每个记录只有一个名为 name 的字段。以下模型设置了表格和关系,因为我相信您需要它们:
from sqlalchemy.schema import UniqueConstraint
class Record(db.Model):
__tablename__ = 'reg_records'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(NVARCHAR())
class Field(db.Model):
__tablename__ = 'reg_fields'
__table_args__ = (
UniqueConstraint('record_id', 'name', name='record_id_name_uix'),
)
id = db.Column(db.Integer, primary_key=True)
record_id = db.Column(db.Integer, ForeignKey(Record.id))
name = db.Column(NVARCHAR())
record = db.relationship(Record, backref='fields')
您现在可以执行创建新记录和字段的操作:
record = Record(title='a record')
record.fields.append(Field(name='field1'))
record.fields.append(Field(name='field2'))
db.session.add(record)
db.session.commit()
但是,尝试为同一个Record创建两个具有相同名称的Fields,当您尝试提交它们时会得到IntegrityError:
record = Record(title='another record')
record.fields.append(Field(name='same_name'))
record.fields.append(Field(name='same_name'))
db.session.add(record)
db.session.commit()
最后,请尝试更加小心Python代码的格式,现在很难阅读。