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

版权声明:本文为geogre123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/geogre123/p/9855648.html