Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I query an association table in SQLAlchemy?

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?

like image 746
Jessi Avatar asked Dec 21 '16 19:12

Jessi


People also ask

How do I run a SQLAlchemy query?

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.

What is Backref in SQLAlchemy?

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.

How would you describe the relationship between tables using ORM?

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.

What is the “association table” in SQL alchemy?

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.

What is the SQLAlchemy object relational mapper?

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.

How to reduce the number of queries in SQLAlchemy queries?

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.

How do you find the parent and child in SQLAlchemy?

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.


1 Answers

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'

like image 123
Jessi Avatar answered Oct 18 '22 14:10

Jessi