一  基本功能

-添加购物车
  -详见代码
-修改课程价格策略
  -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. 一题关于PHP的CTF

    if(isset($_GET['time'])){ if(!is_numeric($_GET['time'])){ echo 'The time must be number.'; }else if( ...

  2. 扩展RBAC用户角色权限设计方案<转>

    RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用户-角色- ...

  3. Linux curl 模拟form表单提交信息和文件

    Linux curl 模拟form表单提交信息和文件   curl是一个命令行方式下传输数据的开源传输工具,支持多种协议:FTP.HTTP.HTTPS.IMAP.POP3.TELNET等,功能超级强大 ...

  4. dp + 状态压缩 - Codeforces 580D Kefa and Dishes

    Kefa and Dishes Problem's Link Mean: 菜单上有n道菜,需要点m道.每道菜的美味值为ai. 有k个规则,每个规则:在吃完第xi道菜后接着吃yi可以多获得vi的美味值. ...

  5. java-----四种引用

    java的四种引用,强弱软虚,用到的场景 标签: java的引用 强弱软虚 2016-05-11 22:59 1237人阅读 评论(0) 收藏 举报 1.强引用(StrongReference) 强引 ...

  6. 【BZOJ】1610: [Usaco2008 Feb]Line连线游戏(几何)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1610 两种做法,一种计算几何,一种解析几何,但是计算几何的复杂度远远搞出解析集合(虽然精度最高) 计 ...

  7. java动态代理中的invoke方法是如何被自动调用的(转)

    一.动态代理与静态代理的区别. (1)Proxy类的代码被固定下来,不会因为业务的逐渐庞大而庞大: (2)可以实现AOP编程,这是静态代理无法实现的: (3)解耦,如果用在web业务下,可以实现数据层 ...

  8. 程序记录2(设置MapID)

    try{ INIT_PLUG I_MongoDB* i = NEW(MongoDB); /*[注] 若自定义错误消息的数组长度必需指定为MAX_ERROR_SIZE*/ //char errmsg[M ...

  9. C 语言开发初涉-01 简单学习

    尝试用C语言写windows程序: 简单的计算器 1.0版,仅用来熟悉C 开发windows的一些语法和语句用法 #include "stdafx.h" #include < ...

  10. 移动端1px细线解决方案--利用transform缩放方式

    移动端1px会显示为2px; 解决方式很多,这里介绍比较常用的一种方式--css的transform属性缩放 1. 上边框 相当于 border-top <div class="bor ...