Запрос множества таблиц за один раз с помощью Flask-SQLAlchemy - PullRequest
0 голосов
/ 06 ноября 2018

Я работаю над веб-приложением, использующим Flask-SQLAlchemy.

Моя модель:

    class Product(db.Model):
    __tablename__ = 'product'
    id = db.Column(db.Integer, primary_key=True)
    ...

    product_to_category = db.relationship('ProductCategory',backref='product', lazy=True)
    shop_products = db.relationship('ShopProducts', backref='product', lazy=True)

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


class ProductDescription(db.Model):
    __tablename__ = 'product_description'
    id = db.Column(db.Integer, primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'))   
    name = db.Column(db.String(255), index=True, unique=False)
    ...

    def __repr__(self):
        return '<ProductDescription: {}>'.format(self.product_id)


class ProductImage(db.Model):
    __tablename__ = 'product_image'
    product_image_id = db.Column(db.Integer, primary_key=True, unique=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'), index=True, unique=False)
    image = db.Column(db.String(255), nullable=True)
    ...

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

class Category(db.Model):
    __tablename__ = 'category'
    id = db.Column(db.Integer, primary_key=True, unique=True)
    parent_id = db.Column(db.Integer, db.ForeignKey('category.id'), index=True, unique=False)
    ...

    products_to_category = db.relationship('ProductCategory',backref='category', lazy=True)

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


class ProductCategory(db.Model):
    __tablename__ = 'product_category'
    id = db.Column(db.Integer, primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'))  
    category_id = db.Column(db.Integer, db.ForeignKey('category.id'))

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


class Shops(db.Model):
    __tablename__ = 'shop'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), index=True, unique=False)
    description = db.Column(db.Text)
    ...

    shop_products = db.relationship('ShopProducts', backref='shop', lazy='joined')

    def __repr__(self):
        return '<Shop: {}>'.format(self.id)


class ShopProducts(db.Model):
    __tablename__ = 'shop_products'      
    id = db.Column(db.Integer, primary_key=True)
    shop_id = db.Column(db.Integer, db.ForeignKey('shop.id'))
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'),index=True)  
    price = db.Column(db.Float,index=True)
    ...

    def __repr__(self):
        return '<Shop Products: {}>'.format(self.price)

Я хочу сделать запрос с фильтрами, чтобы показать все товары в категории и одновременно показать самую низкую цену из таблицы 'shop_products'.

Моя таблица "shop_products":

id shop_id product_id  price

1     1        1       34
2     1        2       56
3     1        3       67
4     2        1       35
5     2        2       55
6     2        3       68
7     3        1       32
8     3        2       58
9     3        4       69
10    4        1       101

Я пытаюсь использовать следующий код, но вижу все продукты на своей html-странице

@site.route('/category/<int:id>', methods=['GET', 'POST'])
def category(id):
    subq = ProductCategory.query.filter_by(category_id=id).subquery()
    product=db.session.query(ProductDescription,ProductImage.image,ShopProducts.price).\
    select_entity_from(subq).\
    filter(ProductDescription.product_id == ProductCategory.product_id). \
    filter(ProductImage.product_id ==  ProductCategory.product_id). \
    filter(ShopProducts.product_id ==  ProductCategory.product_id).\
    order_by(ShopProducts.price.asc())
    return render_template('site/category.html', product=product)

Что я могу сделать? Есть идеи?

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Ваша проблема в том, что вы забыли объединить таблицы в соответствующем столбце (product_id), поэтому sqlalchemy создал таблицу всех возможных комбинаций записей из таблиц.

Попробуйте это

# get all products in requested category
products_in_category = db.session.query(ProductCategory.product_id.label('c_p_id')).filter(
    ProductCategory.category_id==category_id
).subquery()

# get lowest price for each product
product_lowest_price = db.session.query(
    ShopProducts.product_id.label('p_id'), db.func.min(ShopProducts.price).label('lowest_price')
).group_by(ShopProducts.product_id).subquery()

# join all tables by product id
products = db.session.query(
    ProductDescription, ProductImage.image, product_lowest_price.c.lowest_price
).join(
    products_in_category, ProductDescription.product_id==products_in_category.c.c_p_id
).join(
    product_lowest_price, ProductDescription.product_id==product_lowest_price.c.p_id
).filter(ProductDescription.product_id==ProductImage.product_id)
0 голосов
/ 06 ноября 2018

Попробуйте это.

sub = ProductCategory.query.filter_by(category_id=id).subquery()
products = db.session.query(
    ShopProducts).select_entity_from(sub).order_by(
        ShopProducts.price.asc()
        ).all()
...