flask中的关联关系:一对多

模型类

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):
   @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/

 

上一篇:23.泛型让类型更加规范性


下一篇:tp5签到积分兑换商品功能