简体   繁体   English

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

[英]Querying many tables in once with Flask-SQLAlchemy

I'm working on a web application using Flask-SQLAlchemy. 我正在使用Flask-SQLAlchemy开发Web应用程序。

My model is: 我的模型是:

    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)

I want to make a query with filters to show all the products in a category and simultaneously show the lowest price from the 'shop_products' table. 我想使用过滤器进行查询,以显示类别中的所有产品,并同时显示“ shop_products”表中的最低价格。

My 'shop_products' table: 我的“ 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

I try with the following code but i see all products in my html page 我尝试使用以下代码,但在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)

What can i do? 我能做什么? Any ideas? 有任何想法吗?

Try this. 尝试这个。

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

Your problem is that you forgot to join tables on respected column (product_id), so sqlalchemy made table of all possible combinations of entries from tables. 您的问题是您忘记了在受尊敬的列(product_id)上联接表,因此sqlalchemy将表中所有可能的条目组合制成表。

Try this one 试试这个

# 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM