简体   繁体   中英

Sqlalchemy many to many relationship

I have two tables in many to many relationship:

class Association(db.Model):
    __tablename__ = 'association'
    club_id = db.Column(db.Integer, db.ForeignKey('clubs.id'), primary_key=True)
    student_id = db.Column(db.Integer, db.ForeignKey('students.id'), primary_key=True)
    joined_date = db.Column(db.String)
    assoc_student = db.relationship("Student")

class Club(db.Model):
    __tablename__ = 'clubs'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String)
    location = db.Column(db.String)
    club_assoc = db.relationship("Association")

class Student(db.Model):
    __tablename__ = 'students'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    age = db.Column(db.String)
    gender = db.Column(db.String)

Questions:

1) What is the difference between these two queries?

students = db.session.query(Association).filter_by(club_id='1')
students = Association.query.filter_by(club_id='1')

They seem to give the same result!

2) I'm trying to get a list of students with certain age but this following query doesn't work:

db.session.query(Association).filter_by(Association.club_id=='1', Association.assoc_student.age=='15')

But I get this error:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Association.assoc_student has an attribute 'age'

That's why I'm using this one:

db.session.query(Student).join(Association).filter(Association.club_id=='1', Student.age=='15')

Is there a better way to do this without "join"? Maybe with using "backref"!?

1) What is the difference between these two queries?

They do almost the same thing. Former is the way to query objects provided with SQLAlchemy (library Flask uses to access database).

Latter is the convenient way to query models added by Flask-SQLAlchemy library. It makes your queries more readable + extends query with few useful methods. Take a look at source of the flask_sqlalchemy.BaseQuery class to see them: get_or_404() , first_or_404() and paginate() .

Usually you want to use latter method to query objects.

2) I'm trying to get a list of students with certain age but this following query doesn't work.

There are two things here:

  1. Be aware about the difference between filter() and filter_by() methods. In your example you try to use filter_by() with SQL expressions instead of kwargs , which is incorrect.
  2. When you're using filter() you can't specify columns over a relationships (like Association.assoc_student.age ). The only allowed format is ModelName.column_name . That's why it fails.

Is there a better way?

Your second approach is absolutely correct and fine to use. I don't think there is a better way to do it. Alternatively you can use code below to avoid importing db (if you define query in another file):

Student.query.join(Association).filter(Association.club_id == '1', Student.age == '15')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM