zoukankan      html  css  js  c++  java
  • 购物车设计思路

    0.先在redis测试

    # Author:Jesi
    # Time : 2018/10/25 18:36
    import redis
    import json
    conn=redis.Redis(host="47.99.191.149",port=6379,password='cyy520')
    
    # conn.flushall()
    # #购买的第一商品
    # data_dict={
    #     11:{
    #         'title':'21天从入门到放弃',
    #         'src':'xxx.png'
    #     }
    # }
    # conn.hset('luffy_shopping_car','11',json.dumps(data_dict))
    
    # car = conn.hget('luffy_shopping_car','11')
    # car_str=str(car,encoding='utf-8')
    # car_dict=json.loads(car_str)
    # print(car_dict)
    
    # car_dict["12"]={
    #         'title':'luffy_shopping_car',
    #         'src':'xxx2.png'
    #     }
    
    # print(car_dict)
    # print(conn.keys())
    # conn.flushall()
    
    #添加课程
    # redis_key="luffy_shopping_car_%s_%s"%(6,12)
    # conn.hmset(redis_key,{'title':'21天从入门到放弃','src':'xxx.png'})
    
    
    #删除课程
    # conn.delete('luffy_shopping_car_6_12')
    
    
    #修改课程
    # conn.hset('luffy_shopping_car_6_11','src','x1.png')
    
    
    #查看所有课程
    # print(conn.keys('luffy_shopping_car_6_*'))
    
    # for item in conn.scan_iter('luffy_shopping_car_6_*',count=10):
    #     course=conn.hgetall(item)
    #     # print(course)
    #     for k,v in course.items():
    #         print(str(k,encoding='utf-8'),str(v,encoding='utf-8'))

    正式开发购物车的接口:

    因为购物车这种的有可能经常删除,修改等等,我们可以将这个东西放到redis中,速度更快,redis设置过期时间,如果长时间没有结算,那么应该把这个购物车清空。

    添加URL

     url(r'shoppingcar/$',shoppingcar.ShoppingCarViewSet.as_view({'post':'create'}))

    在redis配置上django的redis

    #redis配置
    CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://47.99.191.149:6379",                #redis服务器地址
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
                "CONNECTION_POOL_KWARGS": {"max_connections": 100},  #最大连接池100
                "PASSWORD": "xxxx",
            }
        }
    }

    1.添加购物车接口

    # Author:Jesi
    # Time : 2018/10/26 9:18
    import json
    import redis
    from rest_framework.views import APIView
    from rest_framework.viewsets import GenericViewSet,ViewSetMixin
    from rest_framework.response import Response
    from django_redis import get_redis_connection        #导入django_redis
    from utils.response import BaseResponse              #导入状态信息基类
    from api.views.auth.auth import LuffyAuth            #导入认证组件
    from api import models                                
    from django.core.exceptions import ObjectDoesNotExist
    from utils.exception import PricePolicyInvalid       #自定制的价格策略非法异常
    from django.conf import settings
    
    
    class ShoppingCarViewSet(ViewSetMixin,APIView):
        authentication_classes = [LuffyAuth,]
        conn = get_redis_connection('default')  # 拿到defalut这个redis连接池
    
        def create(self,request,*args,**kwargs):
            '''
            将课程添加到购物车
            :param args:
            :param kwargs:
            :return:
            '''
            ret = BaseResponse()
            self.conn.set("name", "egon")
            try:
                #1.获取用户提交的课程ID和价格策略ID[这里注意int一下]
                course_id=int(request.data.get("courseid"))
                policy_id=int(request.data.get("policyid"))
    
                #2.获取专题课信息
                course=models.Course.objects.filter(id=course_id).first()
    
                #3.获取该课程相关的所有价格策略
                price_policy_list=course.price_policy.all()
                price_policy_dict={}                    #构建一个价格策略的字典。
                for item in price_policy_list:
                    price_policy_dict[item.id]={
                        "period":item.valid_period,
                        "period_display":item.get_valid_period_display(),
                        "price":item.price
                    }
                print(price_policy_dict)
           #{1: {'period': 3, 'period_display': '3天', 'price': 111.0}, 4: {'period': 30, 'period_display': '1个月', 'price': 399.0}}
    #4.判断用户提交的价格策略是否合法 if policy_id not in price_policy_dict: #价格策略不合法 raise PricePolicyInvalid("价格策略不合法") #5.将购物信息添加到redis中 car_key=settings.SHOPPING_CAR_KEY%(request.auth.user_id,course_id) car_dict={ 'title':course.name, 'img':course.course_img, 'default_policy':policy_id, 'policy':json.dumps(price_policy_dict) #这里注意redis中需要将这里dumps一下才可以存入。 } conn=get_redis_connection("default") conn.hmset(car_key,car_dict) ret.data="添加成功!" except PricePolicyInvalid as e: #价格策略非法异常 ret.code=2001 ret.error=e.msg except ObjectDoesNotExist as e: #捕捉课程不存在的异常 ret.code = 2001 ret.error = "课程不存在" except Exception as e: ret.code=1001 ret.error="添加失败" return Response(ret.dict)

    上面用到了一个认证的组件:

    1.独立的认证组件,导入即可

    LuffyAuth.py

    from rest_framework.authentication import BaseAuthentication
    from api import models
    from rest_framework.exceptions import AuthenticationFailed
    
    class LuffyAuth(BaseAuthentication):
    
        def authenticate(self, request):
            """
            用户请求进行认证
            :param request:
            :return:
            """
            # http://wwwww...c0ovmadfasd/?token=adfasdfasdf
            token = request.query_params.get('token')
            obj = models.UserAuthToken.objects.filter(token=token).first()
            if not obj:
                raise AuthenticationFailed({'code':1001,'error':'认证失败'})
    
            return (obj.user.username,obj)

    2.上一个用的封装好的返回信息的基类,导入通用。

    response.py

    class BaseResponse(object):
        '''
        封装一个基础的字典
        '''
        def __init__(self):
            self.code = 1000
            self.data = None
            self.error = None
        @property
        def dict(self):
            return self.__dict__

    3.exception.py

    class PricePolicyInvalid(Exception):
        def __init__(self,msg):
            self.msg=msg

    4.因为常用到这个redis的key,我们放到配置文件,业务中通过settings拿到直接用即可,不用一直写了。

    settings.py

    SHOPPING_CAR_KEY = "luffy_shopping_car_%s_%s"

     

    最后在PY文件中测试一下,看一下redis到底存入了数据没有。

    通过循环,拿到了购物车的数据,表示添加的接口开发完毕!

    2.删除购物车

        #
        def delete(self,request,*args,**kwargs):
            '''
            购物车中删除课程
            :param request:
            :param args:
            :param kwargs:
            :return:
            '''
            ret=BaseResponse()
            try:
                course_id_list=request.data.get("courseids")   #获取到要删除的课程ID,是一个列表,可以删除多个课程
                key_list=[settings.SHOPPING_CAR_KEY%(request.auth.user_id,course_id) for course_id in course_id_list] #构建一个列表
                self.conn.delete(*key_list)                    #使用*直接一起删除掉购物车内的多个选择要删除的课程
            except Exception as e:
                ret.code=1002
                ret.error="删除失败"
            return Response(ret.dict)

    3.修改购物车

        #
        def patch(self,request,*args,**kwargs):
            '''
            修改课程的价格策略
            :param request:
            :param args:
            :param kwargs:
            :return:
            '''
            ret=BaseResponse()
            try:
                #1.获取价格策略ID和课程ID
                course_id=int(request.data.get("courseid"))
                policy_id=int(request.data.get("policyid"))
    
                #2.拼接课程的key
                key=settings.SHOPPING_CAR_KEY%(request.auth.user_id,course_id)
    
                print(key)
                if not self.conn.exists(key):
                    ret.code= 1002
                    ret.error="购物车不存在此课程"
                    return Response(ret.dict)
                #3.在redis中获取所有价格策略:
                policy_dict=json.loads(str(self.conn.hget(key,'policy'),encoding='utf-8'))  #这里需要loads回来并且做一个utf-8的转换
                print(policy_dict)
    
                if str(policy_id) not in policy_dict:                                       #可能出现用户私自修改价格策略,需要做一个判定
                    ret.code=1003
                    ret.error="价格策略不合法"
                    return Response(ret.dict)
    
                #4.在购物车中修改该课程的默认价格策略
                self.conn.hset(key,'default_policy',policy_id)                              #课程和价格策略全部合法后,进行一个修改。
                ret.data="修改成功"
            except Exception as e:
                ret.code=1001
                ret.error="课程修改失败"
    
            return Response(ret.dict)

    4.查看购物车

        #
        def get(self,request,*args,**kwargs):
            '''
            查看购物车中所有的商品
            :param request:
            :param args:
            :param kwargs:
            :return:
            '''
            ret=BaseResponse()
            try:
                current_user_id=request.auth.user_id
                key_match=settings.SHOPPING_CAR_KEY%(current_user_id,"*")   #获取到当前登录用户所有的课程列表
    
                course_list=[]
    
                for key in self.conn.scan_iter(key_match,count=10):         #通过迭代依次取出
                    info={
                        "title" : self.conn.hget(key, "title").decode('utf-8'),
                        "img" : self.conn.hget(key, "img").decode('utf-8'),
                        "policy" : json.loads(self.conn.hget(key, "policy").decode('utf-8')),
                        "default_policy" : self.conn.hget(key, "default_policy").decode('utf-8')
                    }
                    course_list.append(info)   #做成一个列表套字典的形式。
                ret.data=course_list
            except Exception as e:
                ret.code="1001"
                ret.error="获取失败"
    
            return Response(ret.dict)

    获取到的结果显示如下:

    {
        "code": 1000,
        "data": [
            {
                "title": "数学算数",
                "img": "451646",
                "policy": {
                    "2": {
                        "period": 3,
                        "period_display": "3天",
                        "price": 222
                    }
                },
                "default_policy": "2"
            },
            {
                "title": "语文阅读",
                "img": "25852585.jpg",
                "policy": {
                    "1": {
                        "period": 3,
                        "period_display": "3天",
                        "price": 111
                    },
                    "4": {
                        "period": 30,
                        "period_display": "1个月",
                        "price": 399
                    }
                },
                "default_policy": "4"
            }
        ],
        "error": null
    }
    View Code

     完整源码:

    urls.py

    from django.conf.urls import url
    from api.views.course import coursehost
    from api.views.user import account
    from api.views.course import newspapers
    from api.views.shopping import shoppingcar
    
    
    urlpatterns = [
        url(r'^login/$', account.loginView.as_view()),
    
    
        url(r'^course/$', coursehost.CourseViewSet.as_view({"get": "list"})),
        url(r'^course/(?P<pk>d+)/$', coursehost.CourseViewSet.as_view({"get": "retrieve"})),
    
    
    
        url(r'^newspapers/', newspapers.NewsPapers.as_view({"get": "list"})),
        url(r'^newspapers/(?P<pk>d+)/$', newspapers.NewsPapers.as_view({"get": "retrieve"})),
    
    
        url(r'^newspapers/(?P<pk>d+)/agree/$', newspapers.AgreeView.as_view({'post': 'post'})),
    
    
        url(r'shoppingcar/$',shoppingcar.ShoppingCarViewSet.as_view())
    View Code

    shoppingcar.py

    # Author:Jesi
    # Time : 2018/10/26 9:18
    import json
    import redis
    from rest_framework.views import APIView
    from rest_framework.viewsets import GenericViewSet,ViewSetMixin
    from rest_framework.response import Response
    from django_redis import get_redis_connection
    from utils.response import BaseResponse
    from api.views.auth.auth import LuffyAuth
    from api import models
    from django.core.exceptions import ObjectDoesNotExist
    from utils.exception import PricePolicyInvalid
    from django.conf import settings
    
    
    class ShoppingCarViewSet(APIView):
        authentication_classes = [LuffyAuth,]
        conn = get_redis_connection('default')  # 拿到defalut这个redis连接池
    
        #
        def post(self,request,*args,**kwargs):
            '''
            将课程添加到购物车
            :param args:
            :param kwargs:
            :return:
            '''
            ret = BaseResponse()
            self.conn.set("name", "egon")
            try:
                #1.获取用户提交的课程ID和价格策略ID[这里注意int一下]
                course_id=int(request.data.get("courseid"))
                policy_id=int(request.data.get("policyid"))
    
                #2.获取专题课信息
                course=models.Course.objects.filter(id=course_id).first()
    
                #3.获取该课程相关的所有价格策略
                price_policy_list=course.price_policy.all()
                price_policy_dict={}
                for item in price_policy_list:
                    price_policy_dict[item.id]={
                        "period":item.valid_period,
                        "period_display":item.get_valid_period_display(),
                        "price":item.price
                    }
                print(price_policy_dict)
    
                #4.判断用户提交的价格策略是否合法
                if policy_id not in price_policy_dict:
                    #价格策略不合法
                    raise  PricePolicyInvalid("价格策略不合法")
    
                #5.将购物信息添加到redis中
                car_key=settings.SHOPPING_CAR_KEY%(request.auth.user_id,course_id)
                car_dict={
                    'title':course.name,
                    'img':course.course_img,
                    'default_policy':policy_id,
                    'policy':json.dumps(price_policy_dict)
    
                }
                conn=get_redis_connection("default")
                conn.hmset(car_key,car_dict)
                ret.data="添加成功!"
    
            except PricePolicyInvalid as e:
                ret.code=2001
                ret.error=e.msg
            except ObjectDoesNotExist as e:  #捕捉课程不存在的异常
                ret.code = 2001
                ret.error = "课程不存在"
            except Exception as e:
                ret.code=1001
                ret.error="添加失败"
    
            return Response(ret.dict)
    
        #
        def delete(self,request,*args,**kwargs):
            '''
            购物车中删除课程
            :param request:
            :param args:
            :param kwargs:
            :return:
            '''
            ret=BaseResponse()
            try:
                course_id_list=request.data.get("courseids")
                key_list=[settings.SHOPPING_CAR_KEY%(request.auth.user_id,course_id) for course_id in course_id_list]
                self.conn.delete(*key_list)
            except Exception as e:
                ret.code=1002
                ret.error="删除失败"
            return Response(ret.dict)
    
        #
        def patch(self,request,*args,**kwargs):
            '''
            修改课程的价格策略
            :param request:
            :param args:
            :param kwargs:
            :return:
            '''
            ret=BaseResponse()
            try:
                #1.获取价格策略ID和课程ID
                course_id=int(request.data.get("courseid"))
                policy_id=int(request.data.get("policyid"))
    
                #2.拼接课程的key
                key=settings.SHOPPING_CAR_KEY%(request.auth.user_id,course_id)
    
                print(key)
                if not self.conn.exists(key):
                    ret.code= 1002
                    ret.error="购物车不存在此课程"
                    return Response(ret.dict)
                #3.在redis中获取所有价格策略:
                policy_dict=json.loads(str(self.conn.hget(key,'policy'),encoding='utf-8'))
                print(policy_dict)
    
                if str(policy_id) not in policy_dict:
                    ret.code=1003
                    ret.error="价格策略不合法"
                    return Response(ret.dict)
    
                #4.在购物车中修改该课程的默认价格策略
                self.conn.hset(key,'default_policy',policy_id)
                ret.data="修改成功"
            except Exception as e:
                ret.code=1001
                ret.error="课程修改失败"
    
            return Response(ret.dict)
    
        #
        def get(self,request,*args,**kwargs):
            '''
            查看购物车中所有的商品
            :param request:
            :param args:
            :param kwargs:
            :return:
            '''
            ret=BaseResponse()
            try:
                current_user_id=request.auth.user_id
                key_match=settings.SHOPPING_CAR_KEY%(current_user_id,"*")
    
                course_list=[]
    
                for key in self.conn.scan_iter(key_match,count=10):
                    info={
                        "title" : self.conn.hget(key, "title").decode('utf-8'),
                        "img" : self.conn.hget(key, "img").decode('utf-8'),
                        "policy" : json.loads(self.conn.hget(key, "policy").decode('utf-8')),
                        "default_policy" : self.conn.hget(key, "default_policy").decode('utf-8')
                    }
                    course_list.append(info)
                ret.data=course_list
            except Exception as e:
                ret.code="1001"
                ret.error="获取失败"
    
            return Response(ret.dict)
    View Code
  • 相关阅读:
    数据结构
    java web
    C++
    SQL(结构化查询语言)
    网站协议
    python
    爬虫
    select 多选
    List 去除重复数据的五种方式
    oracle锁表SID查询
  • 原文地址:https://www.cnblogs.com/geogre123/p/9855648.html
Copyright © 2011-2022 走看看