使用Flask-SQLAlchemy一次查询多个表

时间:2018-11-06 12:29:10

标签: python flask flask-sqlalchemy

我正在使用Flask-SQLAlchemy开发Web应用程序。

我的模特是:

    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 :(得分:0)

尝试一下。

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

答案 1 :(得分:0)

您的问题是您忘记了在尊敬的列(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)