I'm trying to convert an SQL query into an SQLAlchemy query to user inside get API. The problem is that I cannot query anything from the association table. (I'm sure I don't know the method).
ORM:
roles_users = db.Table(
'roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
)
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(50), unique=True)
description = db.Column(db.String(255))
def __str__(self):
return self.name
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(50))
last_name = db.Column(db.String(50))
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(255))
.
.
.
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
def __str__(self):
return self.email
Working SQL query:
select first_name, last_name, role.name from user
join roles_users
join role on user.id = roles_users.user_id
and role.id = roles_users.role_id;
SQLAlchemy query that I'm having trouble with:
roles_users.query.join(Role).join(User)
.filter(roles_users.user_id == User.id and
roles_users.role_id == Role.id).all()
Error that I'm getting using above SQLAlchemy query:
AttributeError: 'Table' object has no attribute 'query'
How do I perform the equivalent of my SQL query using SQLAlchemy?
Import necessary functions from the SQLAlchemy package. Establish connection with the PostgreSQL database using create_engine() function as shown below, create a table called books with columns book_id and book_price. Insert record into the tables using insert() and values() function as shown.
The sqlalchemy backref is one of the type keywords and it passed as the separate argument parameters which has to be used in the ORM mapping objects. It mainly includes the event listener on the configuration attributes with both directions of the user datas through explicitly handling the database relationships.
A second directive, known as relationship(), tells the ORM that the Invoice class should be linked to the Customer class using the attribute Invoice. customer. The relationship() uses the foreign key relationships between the two tables to determine the nature of this linkage, determining that it is many to one.
This table only contains columns which reference the two sides of the relationship; if it has any other columns, such as its own primary key, or foreign keys to other tables, SQLAlchemy requires a different usage pattern called the “association object”, described at Association Object. We would also like our BlogPost class to have an author field.
The SQLAlchemy Object Relational Mapper presents a method of associating user-defined Python classes with database tables, and instances of those classes (objects) with rows in their corresponding tables.
If you want to reduce the number of queries (dramatically, in many cases), we can apply an eager load to the query operation. SQLAlchemy offers three types of eager loading, two of which are automatic, and a third which involves custom criterion.
If there is a relationship that links a particular Childto each Parent, suppose it’s called Child.parents, SQLAlchemy by default will load in the Child.parentscollection to locate all Parentobjects, and remove each row from the “secondary” table which establishes this link.
Ok, so the key to querying association object in Flask-Sql alchemy is to make an external join to roles_users. Try to join all tables first and then filter afterwards. I'm posting the answer below.
query_user_role = User.query.join(roles_users).join(Role).
filter((roles_users.c.user_id == User.id) & (roles_users.c.role_id == Role.id)).all()
Do not forget to put 'c' when querying association table object. Without it, it won't work.
One more thing, do not forget to set backref lazy = 'joined'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With