大米项目 后端商品部分详解

一.获取商品内容

Ss1. 获取某分类下的商品数据

class CateGoodsView(APIView):
    def get(self, request):
        print(request.META.get("USER"))

        # cate_id = request.query_params.get("cate_id")
        cate_name = request.query_params.get("cate_name")

        # 获取分类信息
        cate_info = Categroy.objects.filter(cate_name=cate_name).first()
        if not cate_info:
            return Response({
                "code": 400,
                "msg": "分类不存在"
            })

        # 通过分类获取分类下商品的信息
        goods_all = cate_info.goods_set.all()[:7]

        # 序列化
        ser = GoodsSer(goods_all, many=True)

        return Response({
            "code": 200,
            "msg": "商品获取成功",
            "goods": ser.data
        })

Ss2. 获取热门商品

class HotGoodsView(APIView):
    def post(self, request):
        cates = request.data.get("cate_name")

        # 查询分类下的热门商品
        goods_all = Goods.objects.filter(cate__cate_name__in=cates).order_by("-count").all()[:7]

        # 序列化
        ser = GoodsSer(goods_all, many=True)

        return Response({
            "code": 200,
            "msg": "热门商品获取成功",
            "goods": ser.data
        })

Ss3. 获取商品详情

class GoodsInfoView(APIView):
    def get(self, request, goods_id):
        # 从数据库获取商品
        goods_info = Goods.objects.filter(id=goods_id).first()

        # 判断商品是否存在
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在",
            })

        # 走到这里,说明商品存在
        # 序列化
        ser = GoodsSer(instance=goods_info, many=False)

        return Response({
            "code": 200,
            "msg": "商品详情获取OK",
            "goods": ser.data
        })

Ss4. 获取商品轮播图

class GoodsInfoImagesView(APIView):
    def get(self, request, goods_id):
        goods_info = Goods.objects.filter(id=goods_id).first()

        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        goods_images = goods_info.goodsimages_set.all()
        print(goods_images)

        # 序列化方式二
        # 手动序列化,把query_set格式的数据,转换为list或dict格式的数据,然后返回就可以了
        img_all = []
        for img_item in goods_images:
            img_all.append({
                "img_path": img_item.img,
                "title": img_item.title,
            })

        return Response({
            "code": 200,
            "msg": "轮播图获取OK",
            "imgs": img_all
        })

二.历史浏览记录

Ss5. 获取历史浏览记录

class HistoryView(APIView):
    def post(self, request, goods_id):
        # 通过检测用户登录中间件给的user数据
        user = request.META.get("USER")

        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录"
            })
        print(user)
        user_id = user["user_id"]  # 拿到了当前用户的ID

        # 判断一下商品是否存在
        goods_info = Goods.objects.filter(id=goods_id).first()
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        # 把浏览记录存到数据库

        r = redis.Redis(host="127.0.0.1", port=6379, password="123456")

        # 分析历史记录的存储格式,使用list比较合适 [1,5,6,2,3,4]
        key = "history:" + str(user_id)  # 3  history:3

        r.lrem(key, 0, goods_id)  # 先从历史记录中移除
        r.lpush(key, goods_id)  # 再添加到redis数据库
        r.ltrim(key, 0, 4)  # 截取最近五条历史记录

        return Response({
            "code": 200,
            "msg": "历史记录添加成功,商品名:" + goods_info.sku_name
        })

    def get(self, request):
        user = request.META.get("USER")
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录",
            })
        user_id = user["user_id"]  # 拿到登录用户的ID

        r = redis.Redis(host="127.0.0.1", port=6379, password="123456")
        key = "history:" + str(user_id)

        goods_list = r.lrange(key, 0, -1)
        goods_all = []
        for item in goods_list:
            goods_id = item.decode()

            goods_info = Goods.objects.filter(id=goods_id).first()
            if not goods_info:
                continue

            goods_all.append(goods_info)

            # goods_list_int.append(item.decode())

        # goods_set = Goods.objects.filter(id__in=goods_list_int)
        #
        ser = GoodsSer(goods_all, many=True)

        return Response({
            "code": 200,
            "msg": "获取历史记录成功",
            "history": ser.data
        })

三.添加收藏

Ss6.添加收藏的类视图

class AddLikeView(APIView):
    def post(self, request, goods_id):
        user = request.META.get("USER")
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录",
            })
        user_id = user["user_id"]  # 拿到登录用户的ID

        # 检测商品是否存在
        goods_info = Goods.objects.filter(id=goods_id).first()
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        r = redis.Redis(host="127.0.0.1", port=6379, password="123456")
        key = "like:" + str(user_id)  # like:3

        # 判断一下,goods_id 是否已经在数据库
        like_goods = r.smembers(key)
        goods_ids = []  # 初始化一个列表,用于存放格式化之后的商品ID

        for gid in like_goods:
            goods_ids.append(gid.decode())

        print(goods_ids)

        if str(goods_id) in goods_ids:
            return Response({
                "code": 400,
                "msg": "已收藏,不用重复收藏"
            })

        r.sadd(key, goods_id)

        return Response({
            "code": 200,
            "msg": "添加收藏成功",
        })

Ss7.展示收藏的类视图

class ShowLikeView(APIView):
    def get(self, request):
        user = request.META.get("USER")
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录",
            })
        user_id = user["user_id"]  # 拿到登录用户的ID

        # 链接redis数据库
        r = redis.Redis(host="127.0.0.1", port=6379, password="123")
        key = "like:" + str(user_id)

        like_goods = r.smembers(key)

        goods_ids = []
        for gid in like_goods:
            goods_ids.append(gid.decode())

        # goods_ids 就是收藏的商品ID

        # 通过goods_ids 查询所有商品信息
        goods_all = Goods.objects.filter(id__in=goods_ids).all()

        # 序列化
        ser = GoodsSer(instance=goods_all, many=True)

        return Response({
            "code": 200,
            "msg": "收藏商品获取成功",
            "goods": ser.data
        })

Ss8.删除收藏的类视图

class DeleteLikeView(APIView):
    def post(self, request, goods_id):
        user = request.META.get("USER")
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录",
            })
        user_id = user["user_id"]  # 拿到登录用户的ID

        # 链接redis数据库
        r = redis.Redis(host="127.0.0.1", port=6379, password="123")
        key = "like:" + str(user_id)

        like_goods = r.smembers(key)

        goods_ids = []
        for gid in like_goods:
            goods_ids.append(gid.decode())

        if str(goods_id) not in goods_ids:
            return Response({
                "code": 400,
                "msg": "没有收藏过"
            })

        r.srem(key, goods_id)

        return Response({
            "code": 200,
            "msg": "删除成功"
        })

四.购物车

Ss9.添加购物车的类视图

class CartView(APIView):
    # 添加购物车
    def post(self, request, goods_id):
        user = request.META.get("USER")  # 获取到中间件检测完登录,传递过来的用户信息,如果未登录,传递过来的是None
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录"
            })
        user_id = user["user_id"]

        r = redis.Redis(host="127.0.0.1", port=6379, password="123")
        # key = "cart:" + str(user_id)
        key = "cart:%s" % user_id

        # 存入数据库
        # 先判断商品是否存在
        goods_info = Goods.objects.filter(id=goods_id).first()
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        cart = {
            "id": goods_id,  # 购物车id
            "productID": goods_id,  # 商品id
            "productName": goods_info.sku_name,  # 商品名称
            "productImg": goods_info.img,
            "price": goods_info.selling_price,  # 商品价格
            "num": 1,  # 加购的商品数量
            "maxNum": goods_info.stock,  # 商品限购数量
            "check": False  # 是否勾选
        }

        # 当前商品是否已经在购物车
        is_exist = r.hexists(key, goods_id)
        if is_exist:
            # 判断一下商品数量是否已经超出库存量
            goods_count = r.hget(key, goods_id)  # 当前商品加入购物车的数量,返回的是byte类型
            goods_count_int = int(goods_count.decode())  # 把byte转换为int
            if goods_count_int >= goods_info.stock:
                # 说明超出库存量,不可以再添加了
                return Response({
                    "code": 400,
                    "msg": "购物车商品已达上限"
                })

            # 购物车数量+1
            r.hincrby(key, goods_id, 1)

            cart["num"] = goods_count_int + 1
            return Response({
                "code": 201,
                "msg": "商品已经在购物车,购物车数量+1",
                "cart": cart,
            })

        else:
            # 把商品添加到购物车
            r.hset(key, goods_id, str(1))

            return Response({
                "code": 200,
                "msg": "加入购物车成功",
                "cart": cart
            })

Ss10.修改购物车数量

    def put(self, request, goods_id):
        user = request.META.get("USER")  # 获取到中间件检测完登录,传递过来的用户信息,如果未登录,传递过来的是None
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录"
            })
        user_id = user["user_id"]  # 当前登录用户
        num = request.data.get("num")  # 修改后的数量

        # 判断一下 商品是否在当前用户的购物车
        r = redis.Redis(host="127.0.0.1", port=6379, password="123")
        key = "cart:%s" % user_id
        is_exists = r.hexists(key, goods_id)  # 判断某商品是否在购物车中
        if not is_exists:  # 不在
            return Response({
                "code": 400,
                "msg": "商品不在购物车中"
            })

        # 判断一下商品是否存在
        goods_info = Goods.objects.filter(id=goods_id).first()
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        # 判断一下是否超出了库存量
        if int(num) > goods_info.stock:
            return Response({
                "code": 400,
                "msg": "超出库存量"
            })

        # 修改数据库中的数据
        r.hset(key, goods_id, num)
        r.close()

        # 返回
        return Response({
            "code": 200,
            "msg": "购物车数量更新成功,当前数量%s" % num
        })

Ss11.删除购物车

   def delete(self, request, goods_id):
        # 判断登录
        user = request.META.get("USER")  # 获取到中间件检测完登录,传递过来的用户信息,如果未登录,传递过来的是None
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录"
            })
        user_id = user["user_id"]

        r = redis.Redis(host="127.0.0.1", port=6379, password="123")
        key = "cart:%s" % user_id
        select_key = "cart_select:%s" % user_id
        # 从购物车删除
        r.hdel(key, goods_id)

        # 从选中的商品中删除
        r.srem(select_key, goods_id)

        # 返回
        return Response({
            "code": 200,
            "msg": "删除成功"
        })

Ss12.查看购物车

class ShowCartView(APIView):
    def get(self, request):
        user = request.META.get("USER")  # 获取到中间件检测完登录,传递过来的用户信息,如果未登录,传递过来的是None
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录"
            })
        user_id = user["user_id"]

        # 获取到redis里面存储的商品信息
        r = redis.Redis(host="127.0.0.1", port=6379, password="123")

        key = "cart:%s" % user_id
        goods_list = r.hgetall(key)

        goods_all = []
        for (k, v) in goods_list.items():
            k = k.decode()  # 商品ID
            v = v.decode()  # 商品加购数量

            goods_info = Goods.objects.filter(id=k).first()
            if not goods_info:  # 商品不存在,跳过该商品
                continue

            select_key = "cart_select:%s" % user_id
            is_exists = r.sismember(select_key, k)

            info = {
                "id": k,  # 购物车id
                "productID": k,  # 商品id
                "productName": goods_info.sku_name,  # 商品名称
                "productImg": goods_info.img,  # 商品图片
                "price": goods_info.selling_price,  # 商品价格
                "num": int(v),  # 加购的商品数量
                "maxNum": goods_info.stock,  # 商品限购数量
                "check": is_exists  # 是否勾选
            }

            goods_all.append(info)

        return Response({
            "code": 200,
            "msg": "购物车获取成功",
            "goods": goods_all
        })

Ss13.购物车全选与取消全选

   def post(self, request):
        # 判断登录
        user = request.META.get("USER")  # 获取到中间件检测完登录,传递过来的用户信息,如果未登录,传递过来的是None
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录"
            })
        user_id = user["user_id"]
        check = request.data.get("check")  # 前台传过来的用户是否全选

        r = redis.Redis(host="127.0.0.1", port=6379, password="123")
        key = "cart:%s" % user_id
        select_key = "cart_select:%s" % user_id

        if check == "check":
            # 执行全选逻辑
            # 获取购物车的所有商品ID
            goods_ids = r.hkeys(key)
            goods_ids_int = []
            for id in goods_ids:
                goods_ids_int.append(id.decode())

            # 把商品ID全部添加到选中的集合里面
            r.sadd(select_key, *goods_ids_int)

            return Response({
                "code": 200,
                "msg": "全选成功"
            })

        # 走到这,就执行全不选的逻辑
        r.delete(select_key)

        return Response({
            "code": 201,
            "msg": "取消全选成功"
        })

Ss14-购物车选中与不选中

class CartCheckView(APIView):
    def post(self, request, goods_id):
        # 判断登录
        user = request.META.get("USER")  # 获取到中间件检测完登录,传递过来的用户信息,如果未登录,传递过来的是None
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录"
            })
        user_id = user["user_id"]

        # 判断商品是否存在
        goods_info = Goods.objects.filter(id=goods_id).first()
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        # 判断商品是否在购物车
        r = redis.Redis(host="127.0.0.1", port=6379, password="123")
        key = "cart:%s" % user_id
        is_exists = r.hexists(key, goods_id)
        if not is_exists:
            return Response({
                "code": 400,
                "msg": "商品不在购物车"
            })

        # 判断商品是否选中
        select_key = "cart_select:%s" % user_id
        is_check = r.sismember(select_key, goods_id)
        if is_check:  # 商品已经选中
            # 执行不选中
            r.srem(select_key, goods_id)

            return Response({
                "code": 201,
                "msg": "取消选中成功"
            })

        # 程序走到这一步,说明商品未选中
        # 执行选中
        r.sadd(select_key, goods_id)

        return Response({
            "code": 200,
            "msg": "选中成功"
        })

五.订单

Ss15-获取 生成 创建 下单

class GoodsView(APIView):
    # 获取订单列表
    def get(self,request):
        user = request.META.get("USER")
        if not user:
            return Response({
                "code":400,
                'msg':"用户未登录"
            })
        user_id = user["user_id"]
        user_info = User.objects.filter(id = user_id).first()
        order_list = user_info.order_set.order_by("-create_time").all() # 拿到用户下面所有的订单

        print(order_list)
        order_all = []
        for order in order_list:
            order_goods_list = order.ordergoods_set.all()

            goods_all = []
            for gd in order_goods_list:
                goods_all.append({
                    "createdTime": order.create_time,
                    "orderID": order.order_id,
                    "payStatus": order.pay_status,
                    "productID": gd.goods.id,
                    "productImg":gd.goods.img,
                    "productName": gd.goods.sku_name,
                    "productNum": gd.count,
                    "productPrice": gd.price
                })
            if not goods_all:
                continue
            order_all.append(goods_all)

        return Response({
            "code":200,
            "msg":"ok",
            "order_list":order_all
        })

    # 生成订单
    def post(self, request):
        # 判断登录
        user = request.META.get("USER")  # 获取到中间件检测完登录,传递过来的用户信息,如果未登录,传递过来的是None
        if not user:
            return Response({
                "code": 400,
                "msg": "用户未登录"
            })
        user_id = user["user_id"]
        addr_id = request.data.get("addr_id")
        goods_list = request.data.get("goods_list")  # [{"goods_id":1,"num":2},{"goods_id":2,"num":2}]
        pay_method = request.data.get("pay_method")

        # 获取收货地址并验证
        addr_info = Addr.objects.filter(id=addr_id, user_id=user_id).first()
        if not addr_info:
            return Response({
                "code": 400,
                "msg": "收货地址不存在"
            })

        # 获取商品信息并验证
        goods_buy = []
        for goods in goods_list:
            goods_info = Goods.objects.filter(id=goods["goods_id"]).first()

            if not goods_info:
                continue

            if goods_info.stock < goods["num"]:
                return Response({
                    "code": 400,
                    "msg": "%s 商品库存不足" % goods_info.sku_name,
                })

            goods_buy.append({
                "id": goods["goods_id"],
                "num": goods["num"],
                "price": goods_info.selling_price
            })

        from django.db import transaction  # 导入事务的类

        with transaction.atomic(): # 开启事务
            point = transaction.savepoint()  # 添加事务的回滚点
            try:
                # 时间戳,时间格式 + userId + 随机数
                from datetime import datetime
                now_time = datetime.now().strftime("%Y%m%d%H%M%S")
                order_id = now_time + str(user_id) + str(random.randint(100000,999999))

                # 创建订单
                order_info = Order.objects.create(
                    order_id=order_id,
                    user_id=user_id,
                    addr=addr_info,
                    total_price=0,
                    total_count=0,
                    pay_method=pay_method,
                    pay_status=1,
                )

                if not goods_buy:
                    transaction.savepoint_rollback(point)  # 事务回滚

                    return Response({
                        "code":400,
                        "msg":"空订单"
                    })
                # 创建订单商品
                for item in goods_buy:
                    # 创建子订单
                    OrderGoods.objects.create(
                        goods_id=item["id"],
                        count=item["num"],
                        price=item["price"],
                        order=order_info,
                    )

                    # 修改主订单的数据
                    order_info.total_price += (item["price"] * item["num"])
                    order_info.total_count += item["num"]

                    # 扣除库存
                    g_info = Goods.objects.filter(id=item["id"]).first()
                    g_info.stock -= item["num"]
                    g_info.save()

                order_info.save()

            except Exception as e:
                transaction.savepoint_rollback(point)
                print(e)
                return Response({
                    "code": 200,
                    "msg": "下单失败"
                })


            # 提交事务
            transaction.savepoint_commit(point)

        # 订单生成完成之后
        from users.views import Pay

        # 生成收银台的地址
        p = Pay()
        url = p.create_order(
            order_id=order_info.order_id,
            amount = str(order_info.total_price)
        )
        # 返回下单成功
        return Response({
            "code": 200,
            "msg": "下单成功",
            "url":url
        })

六.分类

Ss16-商品分类

class CategroyView(APIView):
    def get(self,request):
        cate_list = Categroy.objects.all()
        # 序列化
        cate_all = [{   # 前面追加一个全部
            "id":0,
            "cate":"全部"
        }]
        for cate in cate_list:
            cate_all.append({
                "id":cate.id,
                "cate_name":cate.cate_name
            })
        return Response({
            "code":200,
            "msg":"ok",
            "cate_list":cate_all
        })

路由展示

from django.urls import path
from goods import views

urlpatterns = [
    path("index/cate/goods/", views.CateGoodsView.as_view()),  # 获取分类下商品
    path("index/hot/goods/", views.HotGoodsView.as_view()),  # 获取热门商品
    path("info/<int:goods_id>/", views.GoodsInfoView.as_view()),  # 获取商品详情
    path("info/images/<int:goods_id>/", views.GoodsInfoImagesView.as_view()),  # 获取商品的轮播图
    path("history/<int:goods_id>/", views.HistoryView.as_view()),  # 浏览历史记录
    path("history/", views.HistoryView.as_view()),  # 查看浏览历史记录
    path("add/like/<int:goods_id>/", views.AddLikeView.as_view()),  # 添加收藏
    path("show/like/", views.ShowLikeView.as_view()),  # 查看收藏
    path("delete/like/<int:goods_id>/", views.DeleteLikeView.as_view()),  # 删除收藏
    path("cart/<int:goods_id>/", views.CartView.as_view()),  # 购物车的增删改
    path("cart/check/<int:goods_id>/", views.CartCheckView.as_view()),  # 购物车的选中与不选中
    path("cart/", views.ShowCartView.as_view()),  # 查看购物车、选中购物车
    path("order/", views.GoodsView.as_view()),  # 订单
    path("groy/",views.CategroyView.as_view())  # 商品分类
]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值