简体   繁体   中英

SQLAlchemy Join to retrieve data from multiple tables

I'm trying to retrieve data from multiple tables with SQLAlchemy using the .join() method.

When I run the query I was expecting to get a single object back which had all the data from the different tables joined so that I could use a.area_name and so on where area_name is on one of the joined tables. Below is the query I am running and the table layout, if anyone could offer insight into how to achieve the behavior I'm aiming for I would greatly appreciate it! I've been able to use the .join() method with this same syntax to match results and return them, I figured it would return the extra data from the rows as well since it joins the tables (perhaps I'm misunderstanding how the method works or how to retrieve the information via the query object?).

If it helps with the troubleshooting I'm using MySQL as the database

query:

a = User.query.filter(User.user_id==1).join(UserGroup,
 User.usergroup==UserGroup.group_id).join(Areas, User.area==Areas.area_id).first()

and the tables:

class User(db.Model):
    user_id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), unique=True)
    usergroup = db.Column(db.Integer, db.ForeignKey('user_group.group_id'), nullable=False)
    area = db.Column(db.Integer, db.ForeignKey('areas.area_id'), nullable=False)

class UserGroups(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    group_id = db.Column(db.Integer, nullable=False, unique=True)
    group_name = db.Column(db.String(64), nullable=False, unique=True)


class Areas(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    area_id = db.Column(db.Integer, nullable=False, unique=True)
    area_name = db.Column(db.String(64), nullable=False, unique=True)

Take a look at SQLAlchemy's relationship function:

http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#one-to-many

You may want to add a new attribute to your User class like so:

group = sqlalchemy.relationship('UserGroups', back_populates='users')

This will automagically resolve the one-to-many relationship between User and UserGroups (assuming that a User can only be member of one UserGroup at a time). You can then simply access the attributes of the UserGroup once you have queried a User (or set of Users) from your database:

a = User.query.filter(...).first()
print(a.group.group_name)

SQLAlchemy resolves the joins for you, you do not need to explicitly join the foreign tables when querying.

The reverse access is also possible; if you just query for a UserGroup, you can access the corresponding members directly (via the back_populates -keyword argument):

g = UserGroup.query.filter(...).first()
for u in g.users:
    print(u.name)

So it seems that I need to use a different approach to the query, and that it returns a tuple of objects which I then need to parse.

What worked is:

 a = db.session.query(User, UserGroups, Areas
 ).filter(User.user_id==1
 ).join(UserGroup,User.usergroup==UserGroup.group_id
 ).join(Areas, User.area==Areas.area_id
 ).first()

The rest remaining the same. This then returned a tuple that I could parse where the data from User is a[0], from UserGroups is a[1], and Areas is a[2]. I can then access the group_name column with a[1].group_name etc.

Hopefully this helps someone else who's trying to work with this!

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