Mark Richman
Mark Richman

Reputation: 29710

Flask-SQLAlchemy Querying Many-to-Many

I have a many-to-many relationship between Categories and Products as follows:

category_product = db.Table('category_product',
                            db.Column('category_id',
                                      db.Integer,
                                      db.ForeignKey('category.id')),
                            db.Column('product_id',
                                      db.Integer,
                                      db.ForeignKey('product.id')))


class Product(db.Model):
    """ SQLAlchemy Product Model """
    id = db.Column(db.Integer, primary_key=True)
    sku = db.Column(db.String(10), unique=True, nullable=False)
    name = db.Column(db.String(80), nullable=False)
    categories = db.relationship('Category', secondary=category_product,
                                 backref=db.backref('categories',
                                                    lazy='dynamic'))

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return '<Product {}>'.format(self.name)


class Category(db.Model):
    """ SQLAlchemy Category Model """
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False)
    products = db.relationship('Product', secondary=category_product,
                               backref=db.backref('products', lazy='dynamic'))

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return '<Category {}>'.format(self.name)

I am trying to get all the Product objects in a given Category, specified by category_id:

products = db.session.query(Category).\
        filter_by(id=category_id).\
        products.\
        all()

However, I get the following exception:

AttributeError: 'Query' object has no attribute 'products'

I'm probably missing something simple.

Upvotes: 5

Views: 6959

Answers (2)

Sukma Saputra
Sukma Saputra

Reputation: 1599

For someone who need...

You can use .any()

product = Product.query.filter(Category.products.any(id=cat_id)).all()

I'm not test the query. But I think it's work... Happy coding...

Upvotes: 0

codegeek
codegeek

Reputation: 33309

You cannot follow the filter_by with the attribute name 'products'. You first need to catch the results using all() or first(). Also since you are using Flask-SQLAlchemy, I suggest not using db.session.query(Category) and instead Category.query. So change this

products = db.session.query(Category).\
    filter_by(id=category_id).\
    products.\
    all()

to

all_products = Category.query.\
    filter_by(id=category_id).\
    first().\
    products

Upvotes: 5

Related Questions