如何在Flask-sqlalchemy中创建带额外数据的多对多关联?
我需要把两个模型员工和技能用flask-sqlalchemy关联起来,并且还要加上一些额外的数据。
比如说,用户1可以以100%的效率完成技能1,以80%的效率完成技能2。
所以,我创建了三个模型:
class Employee(db.Model):
__tablename__ = 'employees'
id = db.Column(db.Integer, primary_key=True)
login = db.Column(db.String(64), index=True, unique=True, nullable=False)
skills = db.relationship('Skill', secondary='employee_skills',
backref=db.backref('employees', lazy='dynamic'))
def __repr__(self):
return '<Employee %r, Skills: %r>' % (self.login, self.skills)
class Skill(db.Model):
__tablename__ = 'skills'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), nullable=False, unique=True)
def __repr__(self):
return '<Skill %r>' % self.name
class EmployeeSkill(db.Model):
__tablename__ = 'employee_skills'
employee_id = db.Column(db.Integer, db.ForeignKey('employees.id'), primary_key=True)
skill_id = db.Column(db.Integer, db.ForeignKey('skills.id'), primary_key=True)
efficiency = db.Column(db.Float)
skills_efficiency = db.relationship('Skill', backref=db.backref('employee_efficiency', lazy='dynamic'))
def __repr__(self):
return '<Engineer %r, skill %r, efficiency %r>' % (
self.employee_id, self.skill_id, self.efficiency)
之后我尝试访问这个关联:
>>> from app import db, models
>>> emp_=models.Employee.query.all()
>>> emp_[0]
<Employee u'user1', Skills: [<Skill u'skill1'>, <Skill u'skill2'>]>
>>> emp_[0].skills
[<Skill u'skill1'>, <Skill u'skill2'>]
>>> emp_[0].skills[0]
<Skill u'skill1'>
>>> emp_[0].skills[0].employee_efficiency
<sqlalchemy.orm.dynamic.AppenderBaseQuery object at 0x0000000003A68FD0>
>>> emp_[0].skills[0].employee_efficiency[0]
<Engineer 1, skill 1, efficiency u'1'>
我想要的效果是把员工实例表示成
<Employee u'user1', Skills: <u'skill1', efficiency: '1'>, <u'skill2', efficiency: '0.8'>>
但是我不太明白:我是不是错误使用了db.relationship?还是我需要完善我的repr方法?
提前谢谢你们!
2 个回答
-2
是的,你可以修改一下 repr
方法:
class Skill(db.Model):
__tablename__ = 'skills'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), nullable=False, unique=True)
def __repr__(self):
return '<Skill %r, efficiency: %r>' % (self.name, self.employee_efficiency[0].efficiency)
你已经有了反向引用(backref),所以可以利用这个。
5
当你需要在关联表中添加额外的列时,你需要使用关联对象的方式,而不是使用secondary
属性。这个方式的基本思路是把多对多的关系拆分成两个一对多的关系。
在你的例子中,你可以创建一个从Employee
到EmployeeSkills
的一对多关系,同时保留EmployeeSkills
和Skill
之间的多对一关系。
使用secondary
属性时,SQLAlchemy会自动为你管理关联表。而使用关联对象的方式时,你需要自己管理这个关联表,这样你就可以设置或查询额外的列了。