一  基本功能

-添加购物车
  -详见代码
-修改课程价格策略
  -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",
}
}
}

django-luffycity-购物车接口的更多相关文章

  1. Django day 37 网站视频的播放,购物车接口,优惠券表分析

    一:网站视频的播放, 二:购物车接口, 三:优惠券表分析

  2. 初识Django —Python API接口编程入门

    初识Django —Python API接口编程入门 一.WEB架构的简单介绍 Django是什么? Django是一个开放源代码的Web应用框架,由Python写成.我们的目标是用Python语言, ...

  3. python3.8.0 Django 开发后端接口api 部署到 Linux Centos7上

    经历了两天的时候终于把本地使用python3 django开发的接口API部署到服务器上了,还是记录一下,以免之后忘记,哈哈 注意一点,就是,centos7是基于python2的,我这边默认的是pyt ...

  4. RESTful规范与django编写restful接口

    一.什么是RESTful规范 ①REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” ②REST从资 ...

  5. Django提供后台接口的跨域问题

    --> Django跨域 当使用Django仅用来开发后端接口,为前端提供JSON数据的时候,不可避免的要接受前端的POST请求.虽然Django以其强大易用的特定使用很广泛,但在跨域问题上却让 ...

  6. Django model对象接口

    Django model查询 # 直接获取表对应字段的值,列表嵌元组形式返回 Entry.objects.values_list('id', 'headline') #<QuerySet [(1 ...

  7. django添加REST_FRAMEWORK 接口浏览

    1.安装rest_framework pip install djangorestframework  2.配置rest_framework ## 将rest_framework加入项目app列表 I ...

  8. django开发后台接口error 10053/10054

    初学Django,开发完接口之后访问post请求的接口遇到error10053和10054,查阅很多资料没有找到具体的原因. 在这里记录下我遇到这两个报错的原因和解决方案: get请求取请求参数:su ...

  9. 接口自动化平台搭建(二),搭建django项目与接口自动化平台的由来与功能特征

    1.创建django项目 a.使用命令创建,安装完django之后就有django-admin命令了,执行命令创建即可,命令如下: django-admin startproject my_djang ...

  10. 使用Django开发简单接口:文章增删改查

    目录 1.一些准备工作 安装django 创建django项目 创建博客应用(app) 2.models.py 3.django admin 登录 创建超级用户 4.修改urls.py 5.新增文章接 ...

随机推荐

  1. Unix系统编程()进程和程序

    进程(process)是一个可执行程序(program)的实例. 程序是包含了一系列信息的文件,这些信息描述了如何在运行时创建一个进程,所包括的内容如下所示. 二进制格式标识:每个程序文件都包含用于描 ...

  2. Java解析json(二):jackson

    Java解析json(二):jackson   官方参考 Jackson Home Page:https://github.com/FasterXML/jackson Jackson Wiki:htt ...

  3. Class中isAssignableFrom() 方法

    看Spring源码的时候看到这个方法: protected WebApplicationContext createWebApplicationContext(ServletContext sc) { ...

  4. 【BZOJ】1053: [HAOI2007]反素数ant(贪心+dfs)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1053 约数个数等于分解出的质因数的(指数+1)的乘积这个就不用说了吧... 然后好神的题在于贪心.. ...

  5. Request获取具有相同 name 属性表单元素值

    html代码如: <input name="txtName" id="txtFirstName" type="text" /> ...

  6. &lt;LeetCode OJ&gt; 217./219. Contains Duplicate (I / II)

    Given an array of integers, find if the array contains any duplicates. Your function should return t ...

  7. windows CMD命令大全及详细解释和语法

    http://blog.csdn.net/god_7z1/article/details/51173067

  8. __construct __destory __call __get __set

    1,__construct() 当实例化一个对象的时候,这个对象的这个方法首先被调用. 我们知道 php5对象模型 < ,所以__construct()作为类的默认的构造函数 而不会调用同类名函 ...

  9. 通过python3学习编码

    简介 今天在写python程序的时候,遇到了编码问题,今天,我准备好好了解一下编码问题 ASCII编码 计算机是美国人发明的,最初只有不超过256字符需要编码,1字节能编码2**8个,所以ASCII编 ...

  10. 解析oracle的rownum,数据库查询结果返回行数设置

    对于rownum来说它是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数,而且rownum不能以任何表的名称作为前缀 ...