Flask - 高级查询

查询操作

filter

比较

filter中支持 python中的所有比较运算符: ==!=><>=<=

from flask_restful import Resource, reqparse, marshal_with
from .models import Goods
from .fields import goods_fields


class GoodsView(Resource):

    @marshal_with(goods_fields)
    def get(self):
        # 1. 客户端传递 参数,
        parser = reqparse.RequestParser()
        parser.add_argument('sales', type=int, location=['args'], default=0)
        
        sales = parser.parse_args().get('sales')
        

        # 2. 查询销量大于该参数的所有商品
        goods = Goods.query.filter(Goods.sales > sales).all()
        return goods

注意: 过滤完成之后,还需要调用 all()获取 查询的 结果

逻辑

from flask_restful import Resource, reqparse, marshal_with
from .models import Goods
from .fields import goods_fields
from sqlalchemy import or_, and_, not_


class GoodsView(Resource):

    @marshal_with(goods_fields)
    def get(self):
        # 1. 客户端传递 参数,

        parser = reqparse.RequestParser()
        parser.add_argument('sales', type=int, location=['args'], default=0)
        parser.add_argument('stock', type=int, location=['args'], default=0)

        sales = parser.parse_args().get('sales')
        stock = parser.parse_args().get('stock')

        # 2. 查询销量大于 某个数 或  库存小于 某个数 的商品信息
        goods = Goods.query.filter(or_(Goods.sales > sales, Goods.stock < stock)).all()

        return goods
from flask_restful import Resource, reqparse, marshal_with
from .models import Goods
from .fields import goods_fields
from sqlalchemy import or_, and_, not_


class GoodsView(Resource):
    @marshal_with(goods_fields)
    def get(self):
        # 1. 客户端传递 参数
        parser = reqparse.RequestParser()
        parser.add_argument('max_price', type=float, location=['args'])
        parser.add_argument('min_price', type=float, location=['args'])

        max_price = parser.parse_args().get('max_price')
        min_price = parser.parse_args().get('min_price')

        if (max_price is None) and (min_price is None):
            # 上限  和  下限  都没有
            goods = Goods.query.all()
            
        elif (max_price is None) and (min_price is not None):
            # 有 下限 ,没有 上限
            goods = Goods.query.filter(Goods.price >= min_price).all()
            
        elif (max_price is not None) and (min_price is None):
            # 有 上限 ,没有 下限
            goods = Goods.query.filter(Goods.price <= max_price).all()
            
        else:
            # 查询 价格在某个区间的商品信息
            goods = Goods.query.filter(and_(Goods.price >= min_price, Goods.price <= max_price)).all()

        return goods

  • 模型类.query.filter(模型类.字段 > 值).all(): 比较查询,支持所有比较运算符
  • 模型类.query.filter(or_(条件1, 条件2)).all(): 满足任何一个条件即可
  • 模型类.query.filter(and_(条件1, 条件2)).all(): 满足全部条件即可
  • 模型类.qery.filter(模型类.字段.in_([1, 2, 3, 4])): 查询某个字段是否 在某个 集合中,用来实现 批量操作

判断

# 查询库存不为空 的商品信息
goods = Goods.query.filter(not_(Goods.stock.is_(None))).all()
goods = Goods.query.filter(~(Goods.stock.is_(None))).all()


# id在某个区间的商品信息
goods = Goods.query.filter(Goods.id.in_([1, 3, 6, 7])).all()

模糊查询

from flask_restful import Resource, reqparse, marshal_with
from .models import Goods
from .fields import goods_fields


class GoodsView(Resource):

    @marshal_with(goods_fields)
    def get(self):
        # 
        parser = reqparse.RequestParser()
        parser.add_argument('text', type=str, location=['args'])

        text = parser.parse_args().get('text')
        # sql语句中的模糊查询中, 
        # %: 代表 任意个任意字符
        # _:  代表一个任意字符

        # 查询商品名包含xxx的商品信息
        # goods = Goods.query.filter(Goods.name.like('%{}%'.format(text))).all()

        # 查询 以  xx 开头 的商品信息
        goods = Goods.query.filter(Goods.name.like('{}%'.format(text))).all()

        return goods

排序

from flask_restful import Resource, reqparse, marshal_with
from .models import Goods
from .fields import goods_fields
from sqlalchemy import desc, asc


class GoodsView(Resource):

    @marshal_with(goods_fields)
    def get(self):
        # 接收客户端发送的参数,按照参数进行排序
        parser = reqparse.RequestParser()
        parser.add_argument('params', type=str, location=['args'])

        params = parser.parse_args().get('params')

        if params == 'price':
            goods = Goods.query.order_by('price').all()
        elif params == '-price':
            goods = Goods.query.order_by(desc('price')).all()
        elif params == 'sales':
            goods = Goods.query.order_by('sales').all()
        elif params == '-sales':
            goods = Goods.query.order_by(desc('sales')).all()
        else:
            goods = Goods.query.all()

        return goods

desc(字段): 按照字段 降序排序

asc(字段): 按照字段升序排序,不写asc也是升序排序

关联关系:一对多

模型类

from app.extensions import db


# 商品: 商品属于分类
# 分类   分类反向查询商品
class Cate(db.Model):
    __tablename__ = 'tb_cate'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(20), unique=True)


class Goods(db.Model):
    __tablename__ = 'tb_goods'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), unique=True, nullable=False)
    price = db.Column(db.DECIMAL(8, 2), nullable=False)
    sales = db.Column(db.Integer, default=0)
    stock = db.Column(db.Integer, default=0)
    # 表中实际存在 的 外键字段
    cate_id = db.Column(db.Integer, db.ForeignKey('tb_cate.id'))
    # 字段,表中没有,只是体现 分类和商品的 关联关系, 方便后期的关联查询
    cate = db.relationship('Cate', backref='goods')

序列化字段

from flask_restful import fields

goods_fields = {
    #  和模型类的字段名一一对应
    'id': fields.Integer,
    'name': fields.String,
    'price': fields.String,
    'sales': fields.Integer,
    'stock': fields.Integer,
    # 'cate_id': fields.Integer,  # 直接序列化 外键字段
    
    # 'cate': fields.String,  # 前提是 模型类需要分类模型类 重写 __str__ 方法,返回分类的名字
    
    # 'c_name': fields.String(attribute='cate.name'),  # 自定义字段。需要指明序列化解析的字段,  注意: cate  就是 模型类中的 关联字段
    # 'c_id': fields.Integer(attribute='cate.id'),

    # 将商品对应的分类按照 嵌套格式 进行解析
    "cate": fields.Nested({
        'id': fields.Integer,
        'name': fields.String
    })
}

视图

商品

from flask_restful import Resource, reqparse, marshal_with
from .models import Goods
from .fields import goods_fields
from app.extensions import db


class GoodsView(Resource):
    
    # 商品添加:外键当做普通的字段即可
    def post(self):
        parser = reqparse.RequestParser()

        parser.add_argument('name', type=str, location=['form', 'json'], required=True, help='输入合法的商品名')
        parser.add_argument('price', type=float, location=['form', 'json'], required=True, help='输入合法的商品价格')
        parser.add_argument('stock', type=int, location=['form', 'json'], default=0, help='输入合法的库存')
        parser.add_argument('sales', type=int, location=['form', 'json'], default=0, help='输入合法的销量')
        parser.add_argument('cate_id', type=int, location=['form', 'json'], required=True, help='输入合法的分类id')

        args = parser.parse_args()

        goods = Goods(**args)

        db.session.add(goods)
        try:
            db.session.commit()
        except:
            return {'msg': '添加失败'}, 500
        return {'msg': '添加成功'}, 201
	
    #  查询所有商品,以及对应的分类信息
    @marshal_with(goods_fields)
    def get(self):
        goods = Goods.query.all()
        return goods

分类商品

查询某个分类对应的 商品信息

  • 以商品表为主,通过外键进行过滤查询
class GoodsCateView(Resource):
    
    @marshal_with(goods_fields)
    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument('cate_id', type=int, location='args', required=True, help='需要合适的分类信息')

        cate_id = parser.parse_args().get('cate_id')

        # 以商品表为主,通过外键进行过滤
        goods = Goods.query.filter_by(cate_id=cate_id).all()

        return goods

路由

api.add_resource(GoodsCateView, '/goods/cate/')  
# http://127.0.0.1:5000/goods/cate/?cate_id=xxx
  • 以分类表为主,先查分类对象,再反向查询 对应的商品列表
class CateGoodsView(Resource):
    # cate/xx/goods
    @marshal_with(goods_fields)
    def get(self, pk):
        # 先通过id,查询分类对象
        cate = Cate.query.get_or_404(pk)
        
        # 通过模型类中的  backref 属性 实现  反向查询
        return cate.goods

路由

api.add_resource(CateGoodsView, '/cate/<int:pk>/goods/')
# http://127.0.0.1:5000/cate/xxx/goods/
posted @ 2021-06-03 08:32  罗万  阅读(181)  评论(0)    收藏  举报