zoukankan      html  css  js  c++  java
  • 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",
            }
        }
    }
  • 相关阅读:
    Hibernate---对象的三种状态
    grunt+bower依赖管理
    grunt 的安装和简单使用
    sqlserver dmv 动态管理视图
    ado.net 数据库连接池
    桥接模式
    .net MVP
    主定理(分治算法)
    图中环的判断
    选举协议paxos 协议 理解
  • 原文地址:https://www.cnblogs.com/zhaijihai/p/10192586.html
Copyright © 2011-2022 走看看