Python 炼金术多态关联
我有两个主表,分别是角色和用户,在用户上,我将3个表关联到操作员、教师和学生 到目前为止,我是这样做的:Python 炼金术多态关联,python,postgresql,flask,sqlalchemy,flask-sqlalchemy,Python,Postgresql,Flask,Sqlalchemy,Flask Sqlalchemy,我有两个主表,分别是角色和用户,在用户上,我将3个表关联到操作员、教师和学生 到目前为止,我是这样做的: class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) permissions = db.Column(db.Integer) users
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
permissions = db.Column(db.Integer)
users = db.relationship('User',
backref='role', lazy='dynamic')
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), index=True)
email = db.Column(db.String(64), unique=True, index=True)
password_hash = db.Column(db.String(128))
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
__mapper_args__ = {
'polymorphic_identity': 'users',
'with_polymorphic': '*',
}
class Operator(User):
__tablename__ = 'operator'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
__mapper_args__ = {
'polymorphic_identity': 'operator',
'with_polymorphic': '*'
}
class Teacher(User):
__tablename__ = 'teacher'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
phone_number = db.Column(db.Integer)
other_teacher_data = db.Column(db.String)
__mapper_args__ = {
'polymorphic_identity': 'teacher',
'with_polymorphic': '*'
}
class Student(User):
__tablename__ = 'student'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
other_student_data = db.Column(db.String)
__mapper_args__ = {
'polymorphic_identity': 'student',
'with_polymorphic': '*'
}
但我得到了这个错误信息:
试图将类型为的项刷新为集合的成员
“角色.用户”。应为类型为的对象或的多态子类
这种。如果是的子类,则配置映射器“映射器|用户|用户”
以多态方式加载此子类型,或将enable_typechecks设置为False
允许接受任何子类型进行刷新
我已尝试在角色表中的用户字段上设置启用\u typechecks=False
,然后收到以下错误消息:
psycopg2.errors.UniqueViolation)重复键值违反唯一性
约束“ix_用户\u电子邮件”详细信息:键
(电邮)=(zidanecr7kaka2@gmail.com)已经存在。[SQL:'插入到
用户(已确认、名、姓、电子邮件、密码、,
角色标识、出生日期、地址、创建日期、更新日期)值
(%(已确认)s、%(姓名)s、%(姓氏)s、%(电子邮件)s、,
%(密码散列)s、%(角色id)s、%(出生日期)s、%(地址)s、,
当前\u时间戳,当前\u时间戳)返回用户。id']
[参数:{'confirm':False,'first_name':'Tri','last_name':
'南达','电子邮件':'zidanecr7kaka2@gmail.com“,”密码\u哈希“:
‘pbkdf2:sha1:1000$PtpuVYh4$b5bbb03939cf6ca9013308b62276889d35a8cc1b’,
“角色id”:5,“出生日期”:无,“地址”:无]
即使在尝试使用不同的数据时,我也收到了该消息,但它仍然显示重复的键值
请注意,我的代码有什么问题?或者类似的例子有什么问题?找出区别:)
这不是一条好的错误消息,但是您错过了基类上的type字段。它需要在某个地方存储子表的类型,否则,如果对基类和预期的多态性运行查询,它将不得不搜索所有其他子表以匹配ID。见:
上面,建立了一个附加的列类型作为鉴别器,使用mapper.polymorphic_on参数进行配置。此列将存储一个值,该值指示行中表示的对象类型。列可以是任何数据类型,但字符串和整数是最常见的
虽然多态鉴别器表达式不是严格必需的,但如果需要多态加载,则需要它。在基表上建立一个简单的列是实现这一点的最简单的方法,但是非常复杂的继承映射甚至可以将SQL表达式(如CASE语句)配置为多态鉴别器
在本教程中,他们还建议不要在子项中使用单独的id列,并将子id列的主键和外键都设置回基键
您可能需要删除“with_polymopic”:“*”,因为它预先加载所有子字段(效率低下)。在某些情况下,当您执行筛选时,您可能需要此选项,但您可以在执行查询时启用此选项:
非常感谢,伙计,我错过了类型
字段,同样,你非常棒:)不客气,好问题-很有趣,提供了所有信息。
from app import db
from flask_login import UserMixin
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
permissions = db.Column(db.Integer)
users = db.relationship('User',
backref='role', lazy='dynamic')
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
type = db.Column(db.String(50))
name = db.Column(db.String(64), index=True)
email = db.Column(db.String(64), unique=True, index=True)
password_hash = db.Column(db.String(128))
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
__mapper_args__ = {
'polymorphic_identity': 'users',
'with_polymorphic': '*',
"polymorphic_on": type
}
class Operator(User):
__tablename__ = 'operator'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
__mapper_args__ = {
'polymorphic_identity': 'operator',
'with_polymorphic': '*'
}
class Teacher(User):
__tablename__ = 'teacher'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
phone_number = db.Column(db.Integer)
other_teacher_data = db.Column(db.String)
__mapper_args__ = {
'polymorphic_identity': 'teacher',
'with_polymorphic': '*'
}
class Student(User):
__tablename__ = 'student'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
other_student_data = db.Column(db.String)
__mapper_args__ = {
'polymorphic_identity': 'student',
'with_polymorphic': '*'
}