SQLAlChemy - 模型与表名不同时的外键声明细节

  • 作者:KK

  • 发表日期:2019.08.14


要点速读:

  • 在定义模型关系时,如果被关联模型的名称和它的表名并不完全对应的情况下,外键关联它时要使用它的__tablename__属性来获取表名。讲也讲不清楚,还是往下看吧

假设在一个以p_为表前缀的项目里,有用户表(p_user)和用户组表(p_user_group),对应UserUserGroup模型,定义模型关系时如果两个模型这样写是不对的:

class UserGroup(db.Model):
	__tablename__ = 'p_user_group'

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

	users = db.relationship('User', backref = 'user_group', lazy = True)
	
class User(db.Model):
	__tablename__ = 'p_user'

	id = db.Column(db.Integer, primary_key = True)
	name = db.Column(db.String())
	user_group_id = db.Column(db.Integer, db.ForeignKey('UserGroup.id'), nullable = False)

加载时就会发生如下报错:

Could not determine join condition between 
parent/child tables on relationship CurriculumVersion.enrollments - there are 
no foreign keys linking these tables.  Ensure that referencing columns are 
associated with a ForeignKey or ForeignKeyConstraint, or specify
a 'primaryjoin' expression.

首先UserGroup的定义代码是没错的,主要是User那里,user_group_id的关联定义中的UserGroup.id会被转换成user_group.id,然后查关联数据时就会往user_group这张表去查,结果就没这张表。

正确的定义方式应该是利用被关联模型的__tablename__来拼接:

user_group_id = db.Column(db.Integer, db.ForeignKey(UserGroup.__tablename__ + '.id'), nullable = False)