一、购物车逻辑

吧价格策略+课程id存入redis,传入token进行认证,检验课程是否存在,
价格策略是否合适,也可以存在数据库,我们是存在redis里的,
为什么选择存在redis?
    - 临时状态(之后购物车是需要删除的),这是小公司,为了节省空间, 
        可以用redis定时删除
        
    - 价格策略有可能经常修改
      使用redis主要就是避免对数据库进行重复操作,我们的redis买的是阿里云16G的服务
用户发送POST请求,创建购物车中的一条商品:
    token
    课程ID
    价格策略ID

展示购物车页面发送:GET请求
    获取redis中的所有课程
删除课程:DELETE
修改课程:PATCH
#用POstman运行请求测试

二、代码实现

url.py

urlpatterns = [
    url(r'^shopping_car/$', shopping_car.ShoppingCarView.as_view()),
]

views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from django.core.exceptions import ObjectDoesNotExist
from api import models
from api.utils.auth.api_view import AuthAPIView
from api.utils.exception import PricePolicyDoesNotExist
from pool import POOL
import json
from django.conf import settings

import redis
CONN = redis.Redis(connection_pool=POOL)

class ShoppingCarView(AuthAPIView,APIView):

    def get(self,request,*args,**kwargs):
        """
        查看购物车
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        course = CONN.hget(settings.LUFFY_SHOPPING_CAR,request.user.id)
        course_dict = json.loads(course.decode('utf-8'))
        return Response(course_dict)

    def post(self,request,*args,**kwargs):
        """
        获取课程ID和价格策略ID,放入redis
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        ret = {'code':1000,'msg':None}
        try:
            course_id = request.data.get('course_id')
            price_policy_id = request.data.get('price_policy_id')
            # 1. 获取课程
            course_obj = models.Course.objects.get(id=course_id)

            # 2. 获取当前课程的所有价格策略: id, 有效期,价格
            price_policy_list = []
            flag = False
            price_policy_objs = course_obj.price_policy.all()
            for item in price_policy_objs:
                if item.id == price_policy_id:
                    flag = True
                price_policy_list.append({'id':item.id, 'valid_period':item.get_valid_period_display(),'price':item.price})
            if not flag:
                raise PricePolicyDoesNotExist()

            # 3. 课程和价格策略均没有问题,将课程和价格策略放到redis中
            # 课程id,课程图片地址,课程标题,所有价格策略,默认价格策略
            course_dict = {
                'id':course_obj.id,
                'img':course_obj.course_img,
                'title':course_obj.name,
                'price_policy_list':price_policy_list,
                'default_policy_id':price_policy_id
            }

            # a. 获取当前用户购物车中的课程 car = {1: {,,,}, 2:{....}}
            # b. car[course_obj.id] = course_dict
            # c. conn.hset('luffy_shopping_car',request.user.id,car)
            nothing = CONN.hget(settings.LUFFY_SHOPPING_CAR,request.user.id)
            if not nothing:
                data = {course_obj.id: course_dict}
            else:
                data = json.loads(nothing.decode('utf-8'))
                data[course_obj.id] = course_dict

            CONN.hset(settings.LUFFY_SHOPPING_CAR,request.user.id, json.dumps(data))

        except ObjectDoesNotExist as e:
            ret['code'] = 1001
            ret['msg'] = "课程不存在"
        except PricePolicyDoesNotExist as e:
            ret['code'] = 1002
            ret['msg'] = "价格策略不存在"
        except Exception as e:
            ret['code'] = 1003
            ret['msg'] = "添加购物车异常"

        return Response(ret)

    def delete(self, request, *args, **kwargs):
        res = {
            "state": 10000,
            "data": None,
            "msg": None
        }
        course_id = request.data.get("course_id")
        try:
            cart = json.loads(CONN.hget(settings.SHOPPING_CART_KEY, request.user.id).decode("utf-8"))
            cart.pop(str(course_id))
            CONN.hset(settings.SHOPPING_CART_KEY, request.user.id, json.dumps(cart))
            res["data"] = cart
        except AttributeError:
            # 用户第一次打开购物车,但是第一次打开购物车不可能走到这一步
            res["state"] = 40000
            res["msg"] = "非法操作,请检查数据"
        except KeyError:
            # 购物车已空或者删除不存在的商品,正常流程不会走到这一步
            res["state"] = 40000
            res["msg"] = "非法操作,请检查数据"

        return JsonResponse(res)

    def patch(self, request, *args, **kwargs):
        # 局部更新与post功能重复,建议直接发post请求

        res = ResData(msg="局部更新与post功能重复,请直接发post请求")
        return JsonResponse(res)

    def options(self, request, *args, **kwargs):
        return JsonResponse({
            "state": 10000,
            "data": None,
            "msg": None
        })

三、认证

可以通过继承来做

views.py

from api.utils.auth.auth_view import AuthForView

AuthForView

from api.utils.auth.auth_token import LuffyCityTokenAuth


class AuthForView(object):
    authentication_classes = [LuffyCityTokenAuth, ]

LuffyCityTokenAuth

import datetime

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

from api import models


class LuffyCityTokenAuth(BaseAuthentication):
    keyword = "token"
    model = models.UserAuthToken
    valid_period = 86400000            # 86400000毫秒=24小时
    # valid_period = 100000            # 86400000毫秒=24小时

    res = {
        "state": 40000,
        "data": {
            "back_url": None,
            # "auth_url": None
        },
        "msg": None
    }

    def authenticate(self, request):
        self.res["data"]["back_url"] = request.path_info
        token = request.query_params.get(self.keyword, None)
        if not token:
            self.res["msg"] = "请登录后访问"
            raise AuthenticationFailed(self.res)

        auth = self.model.objects.filter(token=token).first()
        if not auth:
            self.res["msg"] = "认证失败,请重新登录!"
            raise AuthenticationFailed(self.res)

        token_exist_period = self.get_token_exist_period(auth)
        if token_exist_period > self.valid_period:
            self.res["msg"] = "认证已过期,请重新登录!"
            raise AuthenticationFailed(self.res)

        return auth.user, auth

    def get_token_exist_period(self, auth):
        now = datetime.datetime.now()
        return now.timestamp() - auth.created.timestamp()

 

posted on 2018-03-03 19:16  海燕。  阅读(887)  评论(0)    收藏  举报