Reputation: 179
I need to associate two models employee and skill using flask-sqlalchemy with extra data.
For example, user1 can do skill1 with efficiency 100% and skill2 with efficiency 80%.
So, I make 3 models:
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)
After that I try to access to this associantion:
>>> 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'>
What I want is to represent Employee instance as
<Employee u'user1', Skills: <u'skill1', efficiency: '1'>, <u'skill2', efficiency: '0.8'>>
But I don't understand: Do I use db.relationship in a wrong way? Or do I need to complite my repr method?
Thanks in advance
Upvotes: 2
Views: 2703
Reputation: 5682
Yes, you could change the repr
method:
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)
You already have the backref, so use that.
Upvotes: -2
Reputation: 67479
When you need extra columns in the association table you need to use the association object pattern instead of the secondary
attribute. This pattern basically consists in decomposing the many-to-many relationship into two one-to-many relationships.
In your case you would create a one-to-many relationship from Employee
to EmployeeSkills
, and you would keep the many-to-one relationship you already have between EmployeeSkills
and Skill
.
When you use the secondary
attribute SQLAlchemy manages the association table automatically for you. When you use the association object pattern you have to manage the association table yourself, and that gives you access to set or query the extra columns.
Upvotes: 5