zoukankan      html  css  js  c++  java
  • 购物车与结算接口

    购物车中心

    用户点击价格策略加入购物车,个人中心可以查看自己所有购物车中数据~~

    在购物车中可以删除课程,还可以更新购物车中课程的价格策略~~~

    所以接口应该有四种请求方式, get,post,patch,delete~~

    我们在做这个功能之前,首先要讨论我们购物车中数据存在哪~~~为什么要这么存~~

    因为购物车是属于中间状态数据~~而且很多时候需要过期时间~~所以我们选择redis~~

    读取速度快~并且redis可以做持久化~~支持的数据类型也比较多~~

    然后我们需要讨论~我们存redis~~存什么样的数据结构~对于我们实现需求来说更加方便~

    下面看代码中存入redis中的数据结构是什么样的~~

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from utils.authentication import MyAuth
    from utils.redis_pool import POOL
    from utils.base_response import BaseResponse
    import redis
    from couse import models
    import json, datetime
    from utils.exceptions import CommonException
    from django.core.exceptions import ObjectDoesNotExist
    
    SHOPPING_CAR_KEY = "shopping_car_%s_%s"  # 购物车在redis的key
    ACCOUNT_KEY = "account_%s_%s"  # 支付时候用的key
    REDIS_CONN = redis.Redis(connection_pool=POOL)
    
    
    SHOPPING_CAR_KEY = "shopping_car_%s_%s"  # 购物车在redis的key
    ACCOUNT_KEY = "account_%s_%s"  # 支付时候用的key
    REDIS_CONN = redis.Redis(connection_pool=POOL)
    
    
    # shopping_car_ %s_ %s: {
    #     id: 1,
    #     title: CMDB,
    #     course_img: xxxxx,
    #     price_policy_dict: {
    #         1: {"valid_period_text":有效期1个月,"price": 99}
    #       },
    #     default_price_policy_id: 3
    #
    # }    redis库中对应的数据解构(根据查看luffy官网购物车获得)
    
    class ShoppingCar(APIView):
        # 加入购物车必学确认登录(根据token)
        # 添加登录的认证类
        authentication_classes = [MyAuth, ]
    
        def post(self, request):
            res = BaseResponse()
            try:
                # 1 获取前端传过来的course_id 以及price_policy_id user_id
                course_id = request.data.get("course_id", "")
                price_policy_id = request.data.get("price_policy_id", "")
                user_id = request.user.id
                # 2 验证数据的合法性
                # 2.1 验证course_id是否合法
                course_obj = models.Course.objects.filter(id=course_id).first()
                if not course_obj:
                    res.code = 1031
                    res.error = "课程不存在"
                    return Response(res.dict)
                # 2.2 验证价格策略是否合法
                # 该课程的所有价格策略对象
                price_policy_queryset = course_obj.price_policy.all()
    
                # 循环获得每个价格策略的详细信息
                price_policy_dict = {}
                for price_policy_obj in price_policy_queryset:
                    price_policy_dict[price_policy_obj.id] = {
                        "valid_period_text": price_policy_obj.get_valid_period_display(),
                        "price": price_policy_obj.price
                    }
                # 判断价格策略是否在价格策略的字典里
    
                if price_policy_id not in price_policy_dict:
                    res.code = 1032
                    res.error = "价格策略不存在"
                    return Response(res.dict)
                # 3 构建我们想要的数据结构
                course_info = {
                    "id": course_id,
                    "title": course_obj.title,
                    "course_img": str(course_obj.course_img),
                    "price_policy_dict": json.dumps(price_policy_dict, ensure_ascii=False),
                    "default_policy_id": price_policy_id
                }
    
                # 4 写入redis
                # 4.1 先拼接购物车的key
                shopping_car_key = SHOPPING_CAR_KEY % (user_id, course_id)
                # 4.2 写入redis
                print(shopping_car_key, course_info)
                REDIS_CONN.hmset(shopping_car_key, course_info)
                res.data = "加入购物车成功"
            except Exception as e:
                print(str(e))
                # raise
                res.code = 1030
                res.error = "加入购物车失败"
            return Response(res.dict)
    
        def get(self, request):
            res = BaseResponse()
            try:
                # 1 取到user_id
                user_id = request.user.id
                # 2 拼接购物车的key
                shopping_car_key = SHOPPING_CAR_KEY % (user_id, "*")
                # shopping_car_1_*
                # shopping_car_1_asdgnlaksdj
                # 3 去redis读取该用户的所有加入购物车的课程
                # 3.1 先去模糊匹配出所有符合要求的key
                all_key = REDIS_CONN.scan_iter(shopping_car_key)
    
                # 3.2 循环所有的keys  得到每个key
                shopping_car_lsit = []
                for key in all_key:
                    course_info = REDIS_CONN.hgetall(key)
                    course_info["price_policy_dict"] = json.loads(course_info["price_policy_dict"])
                    shopping_car_lsit.append(course_info)
                res.data = shopping_car_lsit
            except Exception as e:
                res.code = 1033
                res.error = "加载购物车失败"
            return Response(res.dict)
    
        def put(self, request):
            res = BaseResponse()
    
            try:
                # 1 获取前端传过来的course_id 以及price_policy_id
                course_id = request.data.get("course_id", "")
                price_policy_id = request.data.get("price_policy_id", "")
                user_id = request.user.id
                # 校验数据的合法性
                # 2.1 校验course_id是否合法
                shoping_car_key = SHOPPING_CAR_KEY % (user_id, course_id)
                if not REDIS_CONN.exists(shoping_car_key):  # 如果不存在
                    res.code = 1035
                    res.error = "课程不存在"
                    return Response(res.dict)
                # 2.2 判断价格策略是否合法
                course_info = REDIS_CONN.hgetall(shoping_car_key)
                price_policy_dict = json.loads(course_info["price_policy_dict"])
                if str(price_policy_id) not in price_policy_dict:
                    res.code = 1036
                    res.error = "所选的价格策略不存在"
                    return Response(res.dict)
                # 修改信息写入redis
                REDIS_CONN.hmset(shoping_car_key, course_info)
                res.data = "更新成功"
            except Exception as e:
                # raise
                res.code = 1034
                res.error = "更新价格策略失败"
            return Response(res.dict)
    
        def delete(self, request):
            res = BaseResponse()
    
            try:
                # 获取前端传过来的course_id
                course_id = request.data.get("course_id", "")
                user_id = request.user.id
                # 判断课程id是否合法
                shopping_car_key = SHOPPING_CAR_KEY % (user_id, course_id)
                if not REDIS_CONN.exists(shopping_car_key):
                    res.code = 1039
                    res.error = "删除的课程不存在"
                    return Response(res.dict)
                # 删除redis中的数据
                REDIS_CONN.delete(shopping_car_key)
            except Exception as e:
                print(str(e))
                res.code = 1037
                res.error = "删除失败"
            return Response(res.dict)
    
    
    class AccountView(APIView):
        """
        结算接口
                    shopping_car_ 1_ 1: {
                    id: 1,
                    title: CMDB,
                    course_img: xxxxx,
                    price_policy_dict: {
                        1: {有效期1个月, 99}
                      },
                    default_price_policy_id: 3
                }
    
                account_%s_%s:{
                    "course_info":{
                                        id: 1,
                                        title: CMDB,
                                        course_img: xxxxx,
                                        price_policy_dict: {
                                            1: {有效期1个月, 99}
                                          },
                                        default_price_policy_id: 3
                                    },
                    "coupons":{
                           1:{},
                           3:{},
                    }
                }
                global_coupon_1:{}
        """
        authentication_classes = [MyAuth, ]
    
        def post(self, request, *args, **kwargs):
            # 获取数据
            user = request.user
            course_id_list = request.data.get("course_id_list", "")
            print(course_id_list)
            response = BaseResponse()
            try:
    
                # 清空操作
                # 找到当前用户所有以account_userid_ *  全部清空
                del_list = REDIS_CONN.keys(ACCOUNT_KEY % (user.pk, "*"))
                print(del_list)
                REDIS_CONN.delete(*del_list)
    
                # 2 创建数据结构
    
                for course_id in course_id_list:
                    account_key = ACCOUNT_KEY % (user.pk, course_id)
                    account_dict = {}
                    shopping_car_key = SHOPPING_CAR_KEY % (user.pk, course_id)
    
                    # 判断课程是否存在在购物车中
                    if not REDIS_CONN.exists(shopping_car_key):
                        raise CommonException("购物车不存在该课程", 1040)
    
                    # 将课程信息加入到没有一个课程结算字典中
                    course_info = REDIS_CONN.hgetall(shopping_car_key)  # 从redis中获取课程信息
                    account_dict["course_info"] = course_info
    
                    # 将课程优惠券加入结算每一个课程结算字典中
    
                    # 查询当前用户拥有未使用的,在有效期的企鹅与当前课程相关的优惠券
                    account_dict["course_coupons"] = self.get_coupon_dict(request, course_id)
    
                    # 将课程优惠券加入结算每一个课程结算字典中get_coupon_dict
    
                    # 存储结算信息
                    REDIS_CONN.set(account_key, json.dumps(account_dict))
    
                # 获取通用优惠券,加入redis中
                REDIS_CONN.set("global_coupon_%s" % user.pk, json.dumps(self.get_coupon_dict(request)))
    
            except CommonException as e:
                response.code = e.code
                response.error = e.msg
            except Exception as e:
                response.code = 500
                response.error = str(e)
    
            return Response(response.dict)
    
        def get_coupon_dict(self, request, course_id=None):
    
            now = datetime.datetime.utcnow()
    
            coupon_record_list = models.CouponRecord.objects.filter(
                user=request.user,
                status=0,
                coupon__valid_begin_date__lte=now,
                coupon__valid_end_date__gt=now,
                coupon__content_type_id=10,
                coupon__object_id=course_id
    
            )
    
            coupon_dict = {}
            for coupon_record in coupon_record_list:
                coupon_dict[coupon_record.pk] = {
                    "name": coupon_record.coupon.name,  # 名字
                    "coupon_type": coupon_record.coupon.get_coupon_type_display(),  # 券类型
                    "money_equivalent_value": coupon_record.coupon.money_equivalent_value,  # 等值货币
                    "off_percent": coupon_record.coupon.off_percent,  # 折扣百分比
                    "minimum_consume": coupon_record.coupon.minimum_consume,  # 最低消费
                    "valid_begin_date": coupon_record.coupon.valid_begin_date.strftime("%Y-%m-%d"),  # 有效期开始时间
                    "valid_end_date": coupon_record.coupon.valid_end_date.strftime("%Y-%m-%d"),  # 有效结束时间
                }
            print(coupon_dict)
            return coupon_dict
    
        def get(self, request):
            pass
    视图
  • 相关阅读:
    写在noi之前
    雅礼集训 Day8
    雅礼集训 Day6
    雅礼集训 Day5
    2017雅礼集训 Day4
    2017雅礼集训 Day2
    2017雅礼集训 Day1
    洛谷 P3426 [POI2005]SZA-Template
    Codeforces Round #368 DIV2 C.
    Educational Codeforces Round 16 D&E.
  • 原文地址:https://www.cnblogs.com/clbao/p/10034220.html
Copyright © 2011-2022 走看看