购物车中心
用户点击价格策略加入购物车,个人中心可以查看自己所有购物车中数据~~
在购物车中可以删除课程,还可以更新购物车中课程的价格策略~~~
所以接口应该有四种请求方式, 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 from course.models import Course import redis import json """ 购物车 redis 的数据结构设计 redis = { shopping_car_<user_id>_<course_id>: { "id": course.id, 带用户id是为了用户查看购物车的时候需要 "title": course.name, "img": str(course.course_img), "policy_dict": { policy_id:{ "period": item.valid_period, 价格策略 "period_display": item.get_valid_period_display(), 价格策略中文 "price": item.price, 价格 }, policy_id2:{ .... } }, "default_policy": policy_id ,选择的价格策略id } } """ REDIS_CONN = redis.Redis(connection_pool=pool) SHOPPING_CAR_KEY = "shopping_car_%s_%s" class ShoppingCarView(APIView): """ 购物车接口 1010 代表成功 1011 课程不存在 1012 价格策略不存在 1013 获取购物车失败 1014 删除的购物车数据不存在 """ authentication_classes = [MyAuth, ] # 展示购物车数据 def get(self, request, *args, **kwargs): res = BaseResponse() # 1 从redis获取购物车数据 try: user_id = request.user.pk shopping_car_key = SHOPPING_CAR_KEY % (user_id, "*") # 用scan_iter方法获取用户购物车的所有key all_keys = REDIS_CONN.scan_iter(shopping_car_key) ret = [] # 循环得到所有想要的数据 for key in all_keys:print(REDIS_CONN.hgetall(key)) ret.append(REDIS_CONN.hgetall(key)) res.data = ret except Exception as e: res.code = 1013 res.error = "获取购物车失败" return Response(res.dict) # 给购物车增加商品 # 传过来的数据 有 课程ID 以及价格策略ID def post(self, request, *args, **kwargs): res = BaseResponse() try: # 1 获取用户提交的课程ID以及价格策略ID course_id = request.data.get("course_id", "") price_policy_id = request.data.get("price_policy_id", "") user_id = request.user.pk # 2 检查用户传过来的数据是否合法 # 2.1 查看课程ID是否存在 course_obj = Course.objects.filter(pk=course_id).first() if not course_obj: res.code = 1011 res.error = "课程对象不存在" # 2.2 查看价格策略是否合法 # 获取该课程的所有价格策略 price_policy_queryset = course_obj.price_policy.all() price_policy_dict = {} for price_policy in price_policy_queryset: price_policy_dict[price_policy.pk] = { "price": price_policy.price, "valid_period": price_policy.valid_period, "valid_period_text": price_policy.get_valid_period_display(), } if price_policy_id not in price_policy_dict: res.code = 1012 res.error = "课程的价格策略不存在" # 3 用户数据合法 得到用户的购物车key shopping_car_key = SHOPPING_CAR_KEY % (user_id, course_id) # 4 构建购物车数据 course_info = { "id": course_id, "title": course_obj.title, "img_src": str(course_obj.course_img), "default_policy": price_policy_id, "price_policy_dict": json.dumps(price_policy_dict) } # 5 写入redis hmset这个方法有值就更新 没值就新建 解决了用户重复点一个商品的问题 REDIS_CONN.hmset(shopping_car_key, course_info) res.data = "加入购物车成功" except Exception as e: print(e) res.code = 1010 res.error = "加入购物车失败" return Response(res.dict) # 删除购物车数据 # 传过来的数据 {course_ids: [1,2]} def delete(self, request, *args, **kwargs): res = BaseResponse() # 1 验证数据合法性 课程ID是否在购物车里 try: for course_id in request.data["course_ids"]: shopping_car_key = SHOPPING_CAR_KEY % (request.user.pk, course_id) if not REDIS_CONN.exists(shopping_car_key): res.code = 1014 res.error = "课程不存在购物车" # 2 数据合法 删除redis购物车里的数据 REDIS_CONN.delete(shopping_car_key) except Exception as e: res.code = 1015 res.error = "删除购物车失败" return Response(res.dict) # 更新购物车里的课程的价格策略 # 传过来的数据 有 course_id 以及 price_policy_id def patch(self, request, *args, **kwargs): res = BaseResponse() # 1 验证数据的合法性 course_id 以及 policy_id try: course_id = request.data["course_id"] policy_id = request.data["price_policy_id"] # 判断redis购物车里是否有course_id shopping_car_key = SHOPPING_CAR_KEY % (request.user.pk, course_id) if not REDIS_CONN.exists(shopping_car_key): res.code = 1014 res.error = "课程不存在购物车" # 判断policy_id 是否合法 price_policy_dict = json.loads(REDIS_CONN.hget(shopping_car_key, "price_policy_dict")) if str(policy_id) not in price_policy_dict: res.code = 1015 res.error = "价格策略不合法" # 2 更改购物车里的数据 REDIS_CONN.hset(shopping_car_key, "default_policy", policy_id) except Exception as e: print(e) res.code = 1016 res.error = "更新购物车失败" return Response(res.dict)