django-luffycity-购物车接口

一  基本功能

-添加购物车
  -详见代码
-修改课程价格策略
  -put或者patch
{"course_id": "1", "policy_id": "1"}
-查看购物车
-删除购物车数据
-购物车数据放在哪?
  -放到redis中,不需要创建mysql的表来存储数据了

二  实现代码

2.1相关表单建立

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey

from django.contrib.contenttypes.fields import GenericRelation
# Create your models here.

# class CourseType(models.Model):


class UserInfo(models.Model):
    name = models.CharField(max_length=64)
    pwd = models.CharField(max_length=32)


class Token(models.Model):
    user = models.OneToOneField(to=UserInfo)
    token = models.CharField(max_length=64)


class Category(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=64)
class Course(models.Model):
    """专题课程"""
    # unique=True 唯一性约束


    name = models.CharField(max_length=128, unique=True)
    course_img = models.CharField(max_length=255)
    brief = models.TextField(verbose_name="课程概述", max_length=2048)

    level_choices = ((0, '初级'), (1, '中级'), (2, '高级'))
    # 默认值为1 ,中级
    level = models.SmallIntegerField(choices=level_choices, default=1)
    pub_date = models.DateField(verbose_name="发布日期", blank=True, null=True)
    period = models.PositiveIntegerField(verbose_name="建议学习周期(days)", default=7)
    # help_text 在admin中显示的帮助信息
    order = models.IntegerField("课程顺序", help_text="从上一个课程数字往后排")

    status_choices = ((0, '上线'), (1, '下线'), (2, '预上线'))
    status = models.SmallIntegerField(choices=status_choices, default=0)
    # 用于GenericForeignKey反向查询,不会生成表字段,切勿删除
    price_policy = GenericRelation("PricePolicy")
    category = models.ForeignKey(to='Category',to_field='nid',null=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = "专题课"


class CourseDetail(models.Model):
    """课程详情页内容"""
    course = models.OneToOneField("Course", on_delete=models.CASCADE)
    hours = models.IntegerField("课时")
    # 课程的标语 口号
    course_slogan = models.CharField(max_length=125, blank=True, null=True)
    # video_brief_link = models.CharField(verbose_name='课程介绍', max_length=255, blank=True, null=True)
    # why_study = models.TextField(verbose_name="为什么学习这门课程")
    # what_to_study_brief = models.TextField(verbose_name="我将学到哪些内容")
    # career_improvement = models.TextField(verbose_name="此项目如何有助于我的职业生涯")
    # prerequisite = models.TextField(verbose_name="课程先修要求", max_length=1024)
    # 推荐课程
    # related_name 基于对象的反向查询,用于替换表名小写_set
    recommend_courses = models.ManyToManyField("Course", related_name="recommend_by", blank=True)
    teachers = models.ManyToManyField("Teacher", verbose_name="课程讲师")

    def __str__(self):
        return "%s" % self.course

    class Meta:
        verbose_name_plural = "课程详细"



class PricePolicy(models.Model):
    """价格与有课程效期表"""
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)  # 关联course or degree_course
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    # course = models.ForeignKey("Course")
    valid_period_choices = ((1, '1天'), (3, '3天'),
                            (7, '1周'), (14, '2周'),
                            (30, '1个月'),
                            (60, '2个月'),
                            (90, '3个月'),
                            (180, '6个月'), (210, '12个月'),
                            (540, '18个月'), (720, '24个月'),
                            )
    valid_period = models.SmallIntegerField(choices=valid_period_choices)
    price = models.FloatField()
    class Meta:
        unique_together = ("content_type", 'object_id', "valid_period")
        verbose_name_plural = "价格策略"

    def __str__(self):
        return "%s(%s)%s" % (self.content_object, self.get_valid_period_display(), self.price)

class Teacher(models.Model):
    """讲师、导师表"""
    name = models.CharField(max_length=32)
    image = models.CharField(max_length=128)
    brief = models.TextField(max_length=1024)

    def __str__(self):
        return self.name

    class Meta:

        verbose_name_plural = "讲师"

2.2自定义response与Exception信息

class MyResponse():
    def __init__(self):
        self.status = 100
        self.msg = None

    @property
    def get_dic(self):
        return self.__dict__



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

2.3登录认证组件

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


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.GET.get('token')
        ret = models.UserToken.objects.filter(token=token).first()
        if ret:
            # 有值说明认证通过,返回两个值
            return ret.user, ret
        else:
            raise AuthenticationFailed('认证失败,没有登录')

2.4views

from rest_framework.views import APIView
from rest_framework.response import Response
from api import models

from api.utils.commonUtils import MyResponse
from rest_framework.viewsets import ViewSetMixin
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from api.utils.MyAuth import LoginAuth
from api.utils.commonUtils import CommonException
from django_redis import get_redis_connection
import json


# 需要登录之后才能操作,写一个认证组件
class ShoppingCart(APIView):
    authentication_classes = [LoginAuth]
    conn = get_redis_connection()

    def post(self, request, *args, **kwargs):
        response = MyResponse()
        # 课程id,价格策略id
        # {"course_id": "1", "policy_id": "1"}
        # 放到redis中key值 shoppingcart_userid_courseid
        # 0 取出课程id,价格策略id
        course_id = str(request.data.get('course_id'))
        policy_id = str(request.data.get('policy_id'))
        # 1 校验课程是否合法
        try:
            course = models.Course.objects.get(pk=course_id)
            # 2 获取所有价格策略(通过课程拿出所有价格策略)
            policy_price_all = course.price_policy.all()
            # 3 从redis中取出当前登录用户的购物车
            shopping_byte = self.conn.get('shoppingcart_%s' % request.user.pk)
            if shopping_byte:
                shopping_cart = json.loads(shopping_byte)
            else:
                shopping_cart = {}
            #     循环构造出价格策略大字典
            policy = {}
            for policy_price in policy_price_all:
                '''
                {
                "period":3,
                "period_display":"3天",
                "price":200
                },
                '''
                policy_one = {
                    'period': policy_price.pk,
                    'period_display': policy_price.get_valid_period_display(),
                    'price': policy_price.price
                }
                policy[str(policy_price.pk)] = policy_one
            #     判断价格策略是否合法,不再字典中,就不合法
            if policy_id not in policy:
                # 不合法
                raise CommonException(102, '价格策略不合法,你不是人')
            # 判断传入的课程id是否在购物车中
            if course_id in shopping_cart:
                # 更新一下默认价格策略
                shopping_cart[course_id]['default_policy'] = policy_id
                response.msg = '更新成功'
            else:
                shopping_course = {
                    'title': course.name,
                    'img': course.course_img,
                    'default_policy': policy_id,
                    'policy': policy
                }

                # 添加到购物车
                shopping_cart[course_id] = shopping_course
                response.msg = '添加成功'
            #     写入redis
            self.conn.set('shoppingcart_%s' % request.user.pk, json.dumps(shopping_cart))

        except ObjectDoesNotExist as e:
            response.status = 101
            response.msg = '该课程不存在,你可能是爬虫'
        except CommonException as e:
            response.status = e.status
            response.msg = e.msg
        except Exception as e:
            response.status = 400
            response.msg = '未知错误'
            print(str(e))
        return Response(response.get_dic)

    def put(self,request,*args,**kwargs):
        response=MyResponse()
        # 0 取出课程id,价格策略id
        course_id = str(request.data.get('course_id'))
        policy_id = str(request.data.get('policy_id'))
        try:
            shopping_byte = self.conn.get('shoppingcart_%s' % request.user.pk)
            if shopping_byte:
                shopping_cart = json.loads(shopping_byte)
            else:
                shopping_cart = {}
            if course_id not in shopping_cart:
                raise CommonException(102,'要修改的课程不存在')
            course_detail=shopping_cart.get(course_id)
            if policy_id not in course_detail['policy']:
                raise CommonException(103, '价格策略不合法')
            course_detail['default_policy']=policy_id
            response.msg='修改成功'
            self.conn.set('shoppingcart_%s' % request.user.pk, json.dumps(shopping_cart))

        except ObjectDoesNotExist as e:
            response.status = 101
            response.msg = '该课程不存在,你可能是爬虫'
        except CommonException as e:
            response.status = e.status
            response.msg = e.msg
        except Exception as e:
            response.status = 400
            response.msg = '未知错误'
            print(str(e))
        return Response(response.get_dic)

    def get(self,request,*args,**kwargs):
        response=MyResponse()
        try:
            shopping_byte = self.conn.get('shoppingcart_%s' % request.user.pk)
            if shopping_byte:
                shopping_cart = json.loads(shopping_byte)
            else:
                shopping_cart = {}
            response.data=shopping_cart

        except Exception as e:
            response.status = 400
            response.msg = '未知错误'
            print(str(e))
        return Response(response.get_dic)

    def delete(self, request, *args, **kwargs):
        response=MyResponse()
        course_id=request.data.get('course_id')
        try:
            shopping_byte = self.conn.get('shoppingcart_%s' % request.user.pk)
            if shopping_byte:
                shopping_cart = json.loads(shopping_byte)
            else:
                shopping_cart = {}
            shopping_cart.pop(course_id,None)
            self.conn.set('shoppingcart_%s' % request.user.pk, json.dumps(shopping_cart))
        except Exception as e:
            response.status = 400
            response.msg = '未知错误'
            print(str(e))
        return Response(response.get_dic)

2.5redis配置

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 1000}
            # "PASSWORD": "123",
        }
    }
}

 

posted @ 2018-12-28 20:17  zhaijihai  阅读(356)  评论(0编辑  收藏  举报