购物车模块

购物车中心

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

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

所以接口应该有四种请求方式, 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)

 

posted @ 2019-05-12 17:15  温而新  阅读(344)  评论(0编辑  收藏  举报