1.redis

2.购物车的构建

api结构:

models.py(创建完后自行添加数据)

  1. from django.db import models
  2. from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
  3. from django.contrib.contenttypes.models import ContentType
  4. # Create your models here.
  5.  
  6. class Course(models.Model):
  7. """专题课/学位课模块表"""
  8. name = models.CharField(max_length=128, unique=True)
  9. course_img = models.CharField(max_length=255)
  10. course_type_choices = ((0, '付费'), (1, 'VIP专享'), (2, '学位课程'))
  11. course_type = models.SmallIntegerField(choices=course_type_choices)
  12. brief = models.TextField(verbose_name="课程概述", max_length=2048)
  13.  
  14. # 用于GenericForeignKey反向查询,不会生成表字段,切勿删除
  15. price_policy = GenericRelation("PricePolicy")
  16.  
  17. class PricePolicy(models.Model):
  18. """价格与有课程效期表"""
  19. content_type = models.ForeignKey(ContentType) # 关联course
  20. object_id = models.PositiveIntegerField()
  21. content_object = GenericForeignKey('content_type', 'object_id')
  22.  
  23. # course = models.ForeignKey("Course")
  24. valid_period_choices = ((1, '1天'), (3, '3天'),
  25. (7, '1周'), (14, '2周'),
  26. (30, '1个月'),
  27. (60, '2个月'),
  28. (90, '3个月'),
  29. (180, '6个月'), (210, '12个月'),
  30. (540, '18个月'), (720, '24个月'),
  31. )
  32. valid_period = models.SmallIntegerField(choices=valid_period_choices)
  33. price = models.FloatField()
  34.  
  35. class Meta:
  36. unique_together = ("content_type", 'object_id', "valid_period")
  37. verbose_name_plural = "15. 价格策略"
  38.  
  39. def __str__(self):
  40. return "%s(%s)%s" % (self.content_object, self.get_valid_period_display(), self.price)
  41.  
  42. class Account(models.Model):
  43. username = models.CharField("用户名", max_length=64, unique=True)
  44. email = models.EmailField(
  45. verbose_name='邮箱',
  46. max_length=255,
  47. unique=True,
  48. blank=True,
  49. null=True
  50. )
  51. password = models.CharField('密码', max_length=128)
  52.  
  53. class Meta:
  54. verbose_name_plural = "22. 账户信息"
  55.  
  56. class UserToken(models.Model):
  57. user = models.OneToOneField(to='Account')
  58. token = models.CharField(max_length=36)
  59.  
  60. class Meta:
  61. verbose_name_plural = "34. token表"  

admin.py(用于在在admin中添加数据)

  1. from django.contrib import admin
  2. from api import models
  3. # Register your models here.
  4.  
  5. admin.site.register(models.UserToken)
  6. admin.site.register(models.Course)
  7. admin.site.register(models.Account)
  8. admin.site.register(models.PricePolicy)

urls.py

  1. from django.conf.urls import url
  2. from api.views import shoppingcar,auth
  3.  
  4. urlpatterns = [
  5. url(r'auth/$', auth.AuthView.as_view({'post': 'login'})),
  6. url(r'shoppingcar/$', shoppingcar.ShoppingCarView.as_view({'post': 'create', 'get': 'list',
  7. 'delete': 'destory', 'put': 'update'})),
  8. ]

 app01下的urls.py

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3.  
  4. urlpatterns = [
  5. url(r'^admin/', admin.site.urls),
  6. url(r'^api/(?P<version>\w+)/', include('api.urls')),
  7. ]

 utils/response.py

  1. class BaseResponse(object):
  2.  
  3. def __init__(self):
  4. self.code = 1000
  5. self.data = None
  6. self.error = None
  7.  
  8. @property
  9. def dict(self):
  10. return self.__dict__

  utils/auth.py(重写用户认证组件)

  1. from rest_framework.authentication import BaseAuthentication
  2. from rest_framework.exceptions import AuthenticationFailed
  3. from api import models
  4.  
  5. class AccountAuthentication(BaseAuthentication):
  6.  
  7. def authenticate(self, request):
  8. """
  9. 源码:
  10. Authenticate the request and return a two-tuple of (user, token).
  11. """
  12. # 从前端获取用户携带的token
  13. token = request.query_params.get('token')
  14. token_obj = models.UserToken.objects.filter(token=token).first()
  15. if not token_obj:
  16. raise AuthenticationFailed({'code':1000,'error':'认证失败'})
  17. # 认证通过
  18. return (token_obj.user, token_obj)

  views/auth.py(登录认证)

  1. import uuid
  2. from rest_framework.views import APIView
  3. from rest_framework.viewsets import ViewSetMixin
  4. from rest_framework.response import Response
  5. from api import models
  6. from api.utils.response import BaseResponse
  7.  
  8. class AuthView(ViewSetMixin,APIView):
  9.  
  10. def login(self,request,*args,**kwargs):
  11. """api_usertoken
  12. 用户登录认证
  13. """
  14. response = BaseResponse()
  15. try:
  16. user = request.data.get('username')
  17. pwd = request.data.get('password')
  18. obj = models.Account.objects.filter(username=user,password=pwd).first()
  19. if not obj:
  20. response.code = 1000
  21. response.error = '用户名或密码错误'
  22. else:
  23. uid = str(uuid.uuid4())
  24. # UserToken和Account是一对一的关系,登陆成功生成uid并加入表格
  25. models.UserToken.objects.update_or_create(user=obj,defaults={'token':uid})
  26. response.code = 99999
  27. response.data = uid
  28.  
  29. except Exception as e:
  30. response.code = 10005
  31. response.error = '操作异常'
  32. return Response(response.dict)

views/shoppingcar.py

  1. import json
  2. import redis
  3. from django.conf import settings
  4.  
  5. from rest_framework.views import APIView
  6. from rest_framework.viewsets import ViewSetMixin
  7. from rest_framework.response import Response
  8.  
  9. from api.utils.auth import AccountAuthentication
  10. from api.utils import response
  11. from api import models
  12.  
  13. # 注意这里的ip地址
  14. CONN = redis.Redis(host="118.24.140.138",port=6379)
  15.  
  16. class ShoppingCarView(ViewSetMixin, APIView):
  17.  
  18. # 加入用户认证
  19. authentication_classes = [AccountAuthentication,]
  20.  
  21. def list(self,request,*args,**kwargs):
  22. """
  23. 从redis中查看购物车信息
  24. """
  25. ret = response.BaseResponse()
  26. try:
  27. shopping_car_list = []
  28. # 这里的request.user来自认证组件的的返回值
  29. print(request.user)
  30. pattern = settings.LUFFY_SHOPPING_CAR % (request.user.id, '*',)
  31. user_key_list = CONN.keys(pattern)
  32. for key in user_key_list:
  33. temp = {
  34. "id":CONN.hget(key,"id").decode("utf-8"),
  35. "name":CONN.hget(key,"name").decode("utf-8"),
  36. "img":CONN.hget(key,"img").decode("utf-8"),
  37. }
  38. shopping_car_list.append(temp)
  39. ret.data = shopping_car_list
  40. except Exception as e:
  41. ret.code = 1000
  42. ret.error = "获取数据失败"
  43.  
  44. return Response(ret.dict)
  45.  
  46. def create(self, request, *args, **kwargs):
  47. """
  48. 加入购物车
  49. """
  50. # 需要先接收用户选中的课程id以及价格策略id
  51. course_id = request.data.get('courseid')
  52. policy_id = request.data.get('policyid')
  53. course = models.Course.objects.first(id=course_id)
  54. ret = response.BaseResponse()
  55. # 判断数据是否合法,防止非正常点击,比如利用其他软件0元购买某些商品
  56. try:
  57. # 判断课程是否存在
  58. if not course:
  59. ret.code = 1000
  60. ret.error = "课程不存在"
  61. return Response(ret.dict)
  62.  
  63. # 判断价格策略的合法性,也是避免蓄意修改
  64. # 获取价格策略的所有信息
  65. price_policy_queryset = course.price_policy.all()
  66. price_policy_dict = {}
  67. for item in price_policy_queryset:
  68. temp = {
  69. 'id':item.id,
  70. 'price':item.price,
  71. 'valid_period': item.valid_period,
  72. 'valid_period_display': item.get_valid_period_display()
  73. }
  74. price_policy_dict[item.id] = temp
  75. # 校验id是是否在字典中
  76. if policy_id not in price_policy_dict:
  77. ret.code = 1000
  78. ret.error = "不要乱动"
  79. return Response(ret.dict)
  80.  
  81. # 设置购物车物品数
  82. pattern = settings.LUFFY_SHOPPING_CAR % (request.user.id, '*',)
  83. keys = CONN.keys(pattern)
  84. if keys and len(keys) >=100:
  85. ret.code = 1000
  86. ret.error = "物品栏已满"
  87. return Response(ret.dict)
  88. except Exception as e:
  89. # 进行添加操作
  90. key = settings.LUFFY_SHOPPING_CAR % (request.user.id, course_id,)
  91. CONN.hset(key,'id',course_id)
  92. CONN.hset(key, 'name', course.name)
  93. CONN.hset(key, 'img', course.course_img)
  94. # 设置保存时长,24h
  95. CONN.expire(key,60*60*24)
  96. ret.code= 500
  97. ret.data = "保存成功"
  98. return Response(ret.dict)
  99.  
  100. def update(self,request,*args,**kwargs):
  101. """
  102. 修改操作,这里我们只能修改我们的价格策略
  103. """
  104. ret = response.BaseResponse()
  105. try:
  106. # 获取用户通过操作相关字段传来的id
  107. course_id = request.data.get('courseid')
  108. policy_id = str(request.data.get('policyid'))
  109.  
  110. key = settings.LUFFY_SHOPPING_CAR % (request.user.id, course_id,)
  111. if not CONN.exists(key):
  112. ret.code = 10000
  113. ret.error = '课程不存在'
  114. return Response(ret.dict)
  115.  
  116. # 取我们存的price_policy_dict数据
  117. price_policy_dict = json.loads(CONN.hget(key, 'price_policy_dict').decode('utf-8'))
  118. # 判断价格策略是否存在
  119. if policy_id not in price_policy_dict:
  120. ret.code = 1000
  121. ret.error = '价格策略不存在'
  122. return Response(ret.dict)
  123. # 修改价格策略
  124. CONN.hset(key, 'default_price_id', policy_id)
  125. set.data = '修改成功'
  126. except Exception as e:
  127. ret.code = 1000
  128. ret.error = "修改失败"
  129. return Response(ret.dict)
  130.  
  131. def destory(self,request,*args,**kwargs):
  132. """
  133. 删除选中的某个课程
  134. """
  135. ret = response.BaseResponse()
  136. try:
  137. course_id = request.data.get('courseid')
  138. # 获取它的key值
  139. key = settings.LUFFY_SHOPPING_CAR % (request.user.id, course_id,)
  140. CONN.delete(key)
  141. ret.data = "删除成功"
  142. except Exception as e:
  143. ret.code = 1000
  144. ret.error = "删除失败"
  145. return Response(ret.dict) 

setting相关配制:

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'app01.apps.App01Config',
  9. 'api.apps.ApiConfig',
  10. 'rest_framework'
  11. ]
  12.  
  13. REST_FRAMEWORK = {
  14. # 版本相关信息
  15. 'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
  16. 'VERSION_PARAM':'version',
  17. 'DEFAULT_VERSION':'v1',
  18. 'ALLOWED_VERSIONS':['v1','v2'],
  19. # 分页相关信息,数字代表一页几条数据
  20. # 'PAGE_SIZE':2
  21. }
  22.  
  23. LUFFY_SHOPPING_CAR = "shopping_car_%s-%s"

测试(成功登录,获取它的token)

发送一个错误请求,这里直接被认证组件拦截了,并没有到达视图

在通过携带token发送一个get请求:

3.全局配置

如果100个类,有98个视图要认证。可以加到全局rest_framework里面

  1. 'DEFAULT_AUTHENTICATION_CLASSES':['api.utils.auth.LuffyAuthentication',]

 对于某些不用认证的类,可以直接定义认证类为空列表即可

  1. authentication_classes = []

  

redis介绍及在购物车项目中的应用,用户认证的更多相关文章

  1. MVC项目中如何判断用户是在用什么设备进行访问

    使用UAParser在C#MVC项目中如何判断用户是在用什么设备进行访问(手机,平板还是普通的电脑) 现在我们开发的很多web应用都要支持手机等移动设备.为了让手机用户能有更加好的用户体验,我们经常为 ...

  2. ssm项目中遇到微信用户名称带有表情,插入失败问题

    ssm项目中遇到微信用户名称带有表情,插入失败问题 问题 Mysql的utf8编码最多3个字节,而Emoji表情或者某些特殊字符是4个字节. 因此会导致带有表情的昵称插入数据库时出错. 解决方法 一. ...

  3. Redis的安装以及在项目中使用Redis的一些总结和体会

    第一部分:为什么我的项目中要使用Redis 我知道有些地方没说到位,希望大神们提出来,我会吸取教训,大家共同进步! 注册时邮件激活的部分使用Redis 发送邮件时使用Redis的消息队列,减轻网站压力 ...

  4. 缓存框架有使用过哪些?memcache和redis有什么区别?项目中,怎么去选择?

    缓存有:ehcache,memcache和redis等 区别: 1. Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等. ...

  5. 【redis】5.spring boot项目中,直接在spring data jpa的Repository层使用redis +redis注解@Cacheable直接在Repository层使用,报错问题处理Null key returned for cache operation

    spring boot整合redis:http://www.cnblogs.com/sxdcgaq8080/p/8028970.html 首先,明确一下问题的场景 之前在spring boot整合re ...

  6. 使用UAParser在C#MVC项目中如何判断用户是在用什么设备进行访问(手机,平板还是普通的电脑)

    现在我们开发的很多web应用都要支持手机等移动设备.为了让手机用户能有更加好的用户体验,我们经常为手机设备专门准备一套前端的页面.这样当用户使用普通电脑来访问的时候,我们的应用就向用户展示普通电脑的页 ...

  7. 在web项目中使用shiro(认证、授权)

    一.在web项目中实现认证 第一步,在web项目中导入shiro依赖的包 第二步,在web.xml中声明shiro拦截权限的过滤器 <filter> <filter-name> ...

  8. 菜鸟-手把手教你把Acegi应用到实际项目中(11)-切换用户

    在某些应用场合中,我们可能需要用到切换用户的功能,从而以另一用户的身份进行相关操作.这一点类似于在Linux系统中,用su命令切换到另一用户进行相关操作.      既然实际应用中有这种场合,那么我们 ...

  9. C#中Fun简单介绍及运用到项目中与缓存(本地缓存,Redis)结合使用

     1.简单介绍Fun C#中Fun和Action有点类似,都是一个委托方法,不同的是Func是有返回值的,而Action没有. (T)此委托封装的方法的参数类型. 备注:详情了解Fun到(https: ...

随机推荐

  1. jQuery中的DOM操作——《锋利的JQuery》

    jQuery封装了大量DOM操作的API,极大提高了操作DOM节点的效率. 1.查找节点 通过我们上一节介绍了JQuery选择器,可以非常轻松地查找节点元素.不过,这时得到的是jQuery对象,只能使 ...

  2. django 将表数据通过API展示到页面上(转)

    需求: 我在learn这个app下创建了两张表,其中一个表为user,我希望通过API,在页面是展示这些数据,当用户访问指定的url时,将表中所有对象展示到页面上. 先看learn/models.py ...

  3. 深入理解JavaScript系列(18):面向对象编程之ECMAScript实现(推荐)

    介绍 本章是关于ECMAScript面向对象实现的第2篇,第1篇我们讨论的是概论和CEMAScript的比较,如果你还没有读第1篇,在进行本章之前,我强烈建议你先读一下第1篇,因为本篇实在太长了(35 ...

  4. jQuery autocomplete 应用

    1. 引入css和js <link rel="stylesheet" href="{{ url_for('static', filename='jquery.aut ...

  5. Razor语句(VIew)小知识

    1.可以写后台语句 例如:

  6. Spring课程 Spring入门篇 4-6 Spring bean装配之基于java的容器注解说明--@ImportResource和@Value java与properties文件交互

    1 解析 1.1 这两个注解应用在什么地方 1.2 应用方式 1.3 xml方式实现取值 2 代码演练 2.1 @ImportResource和@Value代码演练 1 解析 1.1 这两个注解应用在 ...

  7. IO流之序列化流与反序列化流

    序列化流与反序列化流 用于从流中读取对象的 操作流 ObjectInputStream    称为 反序列化流 用于向流中写入对象的操作流 ObjectOutputStream   称为 序列化流 l ...

  8. 原生js简单实现拖拽效果

    实现弹窗拖拽效果的原理是:按下鼠标并移动——拖拽移动物体,抬起鼠标——停止移动.主要触发三个事件:onmousedown.onmousemove以及onmouseup: 首先搭建结构:一个宽350px ...

  9. C#使用Process类杀死进程,执行命令等

    c#之process类相关整理 一.根据进程名获取进程的用户名? 需要添加对 System.Management.dll 的引用 using System.Diagnostics; using Sys ...

  10. iBrand 开源电商小程序 (Laravel API+ webpack + gulp + 原生小程序)

    iBrand 社交电商产品正式进入开源过程中了,我们制定了详细的开源计划,目前已经发布了 V1 的版本,后续的版本也在陆续整理完善中. 各个版本功能明细如下图: 3 个版本计划在今年春节前全部完成,可 ...