zoukankan      html  css  js  c++  java
  • 商城——购物车模块

      在项目中添加商城购物结算模块:

    # 在项目目录下执行如下命令
    $ python3 manage.py startapp shopping

      将应用注册到settings.py中:

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'Course.apps.CourseConfig',
        'Login.apps.LoginConfig',
        'shopping.apps.ShoppingConfig',
        'rest_framework'    # 注意要注册rest_framework
    ]

      将shopping添加到路由分发/LuffyCity/LuffyCity/settings.py:

    from django.contrib import admin
    from django.urls import path, include, re_path
    from django.views.static import serve
    from LuffyCity import settings
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('api/course/', include("Course.urls")),
        path('api/shop/', include("shopping.urls")),   # 顺序早于api/很重要
        path('api/', include("Login.urls")),
    
        # media路径配置
        # path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
        re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})
    ]

    一、添加购物车接口

      前端添加购物车,传给购物车接口的信息会包含course_id、price_policy_id,把购物车的数据放入redis中。保存在redis中的信息其实就是会在前端展示的对应信息。

      设计redis保存的购物车信息主要是:商品名、商品图片、商品价格策略对应价格、用户id、商品id,如下所示:

    {
        SHOPPINGCAR_USERID_COURSE_ID: {
            "id": '',
            "title": '',
            "course_img": '',
            "price_policy_dict": {
                price_policy_id: "{valid_period, price}",
                price_policy_id2: "{valid_period, price}",
                price_policy_id3: "{valid_period, price}"
            },
            "default_price_policy_id": 1
        }
    }

      由于前端显示时,时常需要一个默认的价格,所以还配置一个默认价格策略id字段。

    1、购物车路由

      创建商城路由文件:shopping/urls.py

    from django.urls import path
    from .views import ShoppingCarView
    
    urlpatterns = [
        path('shopping_car', ShoppingCarView.as_view()),   # 购物车
    ]

    2、购物车视图

      购物车视图处理添加购物车的post请求,主要操作:获取前端传递的数据和user_id、校验数据的合法性、构建欲存入redis的key和value、将购物信息写入redis数据库中。

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from utils.base_response import BaseResponse
    from utils.my_auth import LoginAuth
    from utils.redis_pool import POOL
    from Course.models import Course
    import json
    import redis
    
    
    SHOPPINGCAR_KEY = "SHOPPINGCAR_%s_%s"
    CONN = redis.Redis(connection_pool=POOL)    # redis连接
    
    
    class ShoppingCarView(APIView):
        authentication_classes = [LoginAuth, ]    # 登录认证
    
        def post(self, request):
            res = BaseResponse()
            # 1.获取前端传递的数据及user_id
            course_id = request.data.get("course_id", "")
            price_policy_id = request.data.get("price_policy_id", "")
            user_id = request.user.pk    # LoginAuth返回的user_obj即为request.user
            # 2.校验数据的合法性
            # 2.1.校验课程id合法性
            course_obj = Course.objects.filter(id=course_id).first()
            if not course_obj:
                res.code = 1040
                res.error = "课程id不合法"
                return Response(res.dict)
            # 2.2 校验价格策略id是否合法
            price_policy_queryset = course_obj.price_policy.all()
            price_policy_dict = {}
            for price_policy in price_policy_queryset:
                price_policy_dict[price_policy.id] = {
                    "price": price_policy.price,   # 价格
                    "valid_period": price_policy.valid_period,   # 周期
                    "valid_period_display": price_policy.get_valid_period_display()   # 周期中文
                }
            print("价格策略", price_policy_id, price_policy_dict)
            if price_policy_id not in price_policy_dict:
                res.code = 1041
                res.error = "价格策略id不合法"
                return Response(res.dict)
            # 3.构建redis Key
            key = SHOPPINGCAR_KEY % (user_id, course_id)
            # 4.构建redis数据结构
            course_info = {
                "id": course_obj.id,
                "title": course_obj.title,
                "course_img": str(course_obj.course_img),    # 解决字典类型不一致的问题
                # 所有放入redis的字典最好做一下json.dumps,防止出现格式问题或中文乱码
                "price_policy_dict": json.dumps(price_policy_dict, ensure_ascii=False),
                "default_price_policy_id": price_policy_id
            }
            # 5.写入redis
            CONN.hmset(key, course_info)
            res.data = "加入购物车成功"
            return Response(res.dict)

    3、添加购物车接口测试

      首先调用登录接口获取token:

      

       然后配置购物车header:

      

      随后调用添加购物车接口

      

    二、查看购物车接口

      通过redis拿到购物车的所有信息进行展示。

    1、查看购物车接口视图

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from utils.base_response import BaseResponse
    from utils.my_auth import LoginAuth
    from utils.redis_pool import POOL
    from Course.models import Course
    import json
    import redis
    
    
    SHOPPINGCAR_KEY = "SHOPPINGCAR_%s_%s"       # 第一个值user_id,第二个值course_id
    CONN = redis.Redis(connection_pool=POOL)    # redis连接
    
    
    class ShoppingCarView(APIView):
        authentication_classes = [LoginAuth, ]    # 登录认证
        def post(self, request):...
    
        def get(self, request):
            res = BaseResponse()
            # 1.拼接redis KEY
            user_id = request.user.pk
            shopping_car_key = SHOPPINGCAR_KEY % (user_id, "*")   # redis支持模糊匹配
            # 2.去redis中读取数据
            # 2.1 匹配所有的keys
            all_keys = CONN.scan_iter(shopping_car_key)    # 都匹配,返回的是生成器
            ret = []
            for key in all_keys:
                ret.append(CONN.hgetall(key))
            print(ret)
            # 3.构建数据结构展示
            res.data = ret
            return Response(res.dict)

    (1)scan_iter(match=None, count=None)

      查看所有元素-迭代器

    (2)hgetall(name)

      获取name对应hash的所有键值。

    2、查看购物车接口测试

      

    三、更新购物车接口

      在更新购物车时,同样需要前端提供course_id和price_policy_id,校验数据合法后,更新redis中的default_price_policy_id字段。

    1、更新购物车视图

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from utils.base_response import BaseResponse
    from utils.my_auth import LoginAuth
    from utils.redis_pool import POOL
    from Course.models import Course
    import json
    import redis
    
    
    SHOPPINGCAR_KEY = "SHOPPINGCAR_%s_%s"       # 第一个值user_id,第二个值course_id
    CONN = redis.Redis(connection_pool=POOL)    # redis连接
    
    class ShoppingCarView(APIView):
        authentication_classes = [LoginAuth, ]    # 登录认证
    
        def post(self, request):...
    
        def get(self, request):...
    
        def put(self, request):
            # 更新购物车:前端需要提供course_id、price_policy_id
            res = BaseResponse()
            # 1.获取前端传过来的数据及user_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 course_id是否合法
            key = SHOPPINGCAR_KEY % (user_id, course_id)
            if not CONN.exists(key):    # exists检查名字是否存在
                res.code = 1043
                res.error = "课程id不合法"
                return Response(res.dict)
            # 2.2 price_policy_id是否合法
            price_policy_dict = json.loads(CONN.hget(key, "price_policy_dict"))
            if str(price_policy_id) not in price_policy_dict:
                res.code = 1044
                res.error = "价格策略不合法"
                return Response(res.dict)
            # 3.更新redis中的default_price_policy_id字段
            CONN.hset(key, "default_price_policy_id", price_policy_id)
            res.data = "更新成功"
            return Response(res.dict)

    2、更新购物车测试

      更新token,发送put请求:

      

       发送get请求,验证更新结果:

       

    四、删除购物车接口

      考虑可能会批量删除,前端传递过来的数据应该是用一个列表course_list,来保存一个一个course_id。循环校验这些课程id是否合法,再删除redis中的数据。

    1、删除购物车视图

    class ShoppingCarView(APIView):
        """代码省略"""
        def delete(self, request):
            # course_list = [course_id, ]
            res = BaseResponse()
            # 1.获取前端传来的数据及user_id
            course_list = request.data.get("course_list", "")
            user_id = request.user.pk
            # 2.校验course_id是否合法
            for course_id in course_list:
                key = SHOPPINGCAR_KEY % (user_id, course_id)
                if not CONN.exists(key):   # 如果key不存在
                    res.code = 1045
                    res.error = "课程id不合法"
                    return Response(res.dict)
                # 3.删除redis数据
                CONN.delete(key)
            res.data = "删除成功"
            return Response(res.dict)

    2、删除购物车测试

      更新token,发送delete请求:

      

      发送get请求,验证删除结果:

      

    五、总结和优化

      这些接口要进一步优化,应该在最外层套一层try,同时应该添加大量的日志打印功能,方便后期运维。

  • 相关阅读:
    FCM模糊c均值聚类
    Iris数据集免费下载
    matlab 信息增益函数 入侵检测kudcupp
    KNN分类算法的实现
    Git远程仓库地址变更本地如何修改
    浅析 UART、RS232、TTL 之间的关系(转)
    编译某一个ko模块make modules SUBDIRS=drivers/xxx/
    Linux系统调用之SYSCALL_DEFINE(转)
    【TCP/IP详解】TCP保活机制(转)
    linux cpu、内存、IO、网络的测试工具(转)
  • 原文地址:https://www.cnblogs.com/xiugeng/p/12096779.html
Copyright © 2011-2022 走看看