Django知识点回顾

Django REST framework

https://www.django-rest-framework.org/

Django REST框架是一个功能强大且灵活的工具包,用于构建Web API。
您可能希望使用REST框架的一些原因:

  • 该网站可浏览API是你的开发人员一个巨大的可用性胜利。
  • 身份验证策略包括OAuth1a和OAuth2的程序包。
  • 支持ORM和非ORM数据源的序列化。
  • 可自定义 - 如果您不需要更强大的功能,只需使用常规的基于功能的视图。
  • 丰富的文档和良好的社区支持。
  • 受到国际知名公司的使用和信任,包括Mozilla,Red Hat,Heroku和Eventbrite

Redis

Redis 是完全开源免费的,遵守BSD协议(五大开源协议中的一个),是一个高性能的key-value数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:

  1. Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  2. Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  3. Redis支持数据的备份,即master-slave模式的数据备份。
  • Redis应用场景
    • 适用场景:对速度有要求, 需要设置过期时间, 并且数据关系不复杂
    • session存储 (性能更好, 方便设置过期时间)
    • 购物车 (以请求令牌token作为key,记录当前用户购物车中的商品及其数量)
    • 网页缓存 (将 请求的url/返回的网页内容 作为redis的key/value进行缓存)
    • 实时排行 (利用zset的数据权重分析数据排行, 按排名展示数据)
2. 配置

Django默认提供的认证系统中,用户的认证机制依赖Session机制,我们在本项目中将引入JWT认证机制,将用户的身份凭据存放在Token中,然后对接Django的认证系统

  1. 用户的数据模型
  2. 用户密码的加密与验证
  3. 用户的权限系统

项目分为:

  1. 用户部分
  2. 商品部分
  3. 购物车部分
  4. 订单部分
  5. 支付部分
  6. 搜索模块

项目采用技术

  1. 采用前后端分离技术
  2. 后端使用DRF框架实现整个项目的接口(API)部分
  3. 前端使用vue.js

短信验证码

后端开发流程

发送短信的接口,携带数据以路劲参数的形式,get应该返回当前请求资源的请求数据,在这里资源数据发送到手机上,不需要返回给前端页面,所以直接返回一个OK就可以
定义接口
请求方式 get
请求路径 以名词复数形式来写 短信验证码 sms_codes/
携带数据 mobile 有请求头部、请求体、json字符串、表单、路径参数等形式
返回结果 OK

json数据、表单数据统一用request.data来获取
前端根据接口
前端根据接口发送ajax请求,ajax.get(路径参数),ajax.get(“sms_codes/13111111111”)
Response.data
通过response.data接收请求结果

后端根据接口填写代码

class View(APIView):
    
    def get(self,request,mobile)  以请求路劲的形式直接在括号里填入请求路径中需要的参数
    	# request.query_pramas 获取查询字符串
        # request.data. # 获取请求体数据
        
        # 序列化器
        ser = Serializers()  APIview直接使用序列化器来生成序列化器对象
        ser= self.get_serialzier()  GenrecAPIview
        这俩个差不多,只要业务逻辑中不涉及分页、过滤俩个都可以使用,如果业务逻辑中涉及到分页和过滤处理的话,只能使用GenrecAPIview,因为只有GenrecAPIview才提供了分页、过滤属性,

        
        # 生成短信验证码
        
        # 保存短信验证码
        
        # 发送短信
        
        # 返回结果
class Serialzers(ModelSerializer)
序列化器选择,只要操作的字段和模型类没有关系,就选择Serializer
如果操作的字段和模型类有关系就使用ModelSerializer

	sms_codes=serializer.CharField()
  	class Meta:
        model=User
        fields=('sms_codes','usernam','mobile')   字段指明时,给他显示出来就额可以了
        
        
    def create():   ModelSerializer中这个方法已经实现过了,实现的逻辑是固定的,如果发现固定的业务逻辑不够用,可以将方法进行重写

如果不断刷新请求页面,后端也需要不断接受请求,如果受到恶意代码(写一个while循环,不断请求服务器,如果写多个线程,如100个,那么服务器同一时间要处理100个请求,如果请求过多,服务器承受不了就会蹦)的操作,会增加后端服务器的压力。可以通过限流解决,还可以通过时间进行判断。

短信验证码不需要长期存储,可以使用Redis数据库进行存储,指定一个缓存数据库来存储短信验证码,并设置过期时间。配置文件中配置缓存Redis数据库

判断60秒时在缓存中写入判断依据,

Redis数据库操作网站Redis.cn

使用随机数生成6位数短信验证码,将生成的短信验证码写入Redis数据库verify,使用setex这个方法将验证码写入,短信验证码首先想到随机数

导入人熔炼云通讯的包,然后在发送短信的代码中导入云通讯的模块实现发送短信功能CCP,发送短信时可能需要多次,所以将请求放入管道中,一次完成pipeline
管道原理
Django知识点回顾_第1张图片

如果网络状态不好的话,回导致请求一直阻塞等待在这里,所以要解决这个问题需要用到celery异步任务队列,celery由broke(任务队列)、worker任务执行者可以去任务队列中找到方法,开辟一个线程去执行这个任务。
如何去调用队列中的方法,需要通过delay方法来通知worker来执行这个任务,worker会去任务队列中查询这个方法,如果有这个任务方法,就会开辟一个线程去执行这个任务。

Django知识点回顾_第2张图片
celery使用需要单独创建一个文件夹,celery_tasks来使用,首先配置config

broker_url = "redis://127.0.0.1/14"

然后在main.py中配置,celery的启动文件

from celery import Celery

# 为celery使用django配置文件进行设置
import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev'

# 创建celery应用
app = Celery('meiduo')

# 导入celery配置
app.config_from_object('celery_tasks.config')

# 自动注册celery任务  sms、email代表创建的目录名字,目录用来存放定义的任务
app.autodiscover_tasks(['celery_tasks.sms','celery_tasks.email','celery_tasks.html'])


# celery -A celery_tasks.main worker -l info

创建sms/tasks.py,tasks.py必须使用这个名字,创建完成后在main.py文件中添加sms这个任务’celery_tasks.sms’

注意点:添加了异步任务后需要在运行代码的时候,开启异步任务,不然会报无法连接,拒绝连接的错误

from meiduo_mall.libs.yuntongxun.sms import CCP
from celery_tasks.main import app

@app.task(name='send_sms_code')
def send_sms_code(mobile,sms_code):
    ccp=CCP()
    ccp.send_template_sms(mobile,[sms_code,'5'],1)

@app.task(name='a_print')
def a_print():
    print(1111)

写完要在当前目录下配置路由,并且全局路由也需要匹配

# 全局路由 需要导入include
 url(r'^', include('verifications.urls')),

from django.conf.urls import url
from django.contrib import admin
from .  import views

urlpatterns = [
    url(r'^sms_codes/(?P1[3-9]\d{9})/$', views.SMSCodeView.as_view()),
]
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from random import randint
from django_redis import get_redis_connection
from meiduo_mall.libs.yuntongxun.sms import CCP
from celery_tasks.sms.tasks import send_sms_code


# Create your views here.
class SMSCodeView(APIView):
    def get(self, request, mobile):
        # 判断60s
        conn = get_redis_connection('verify')
        flag = conn.get('sms_flag_%s' % mobile)
        if flag:
            return Response({'message': '请求过于频繁'}, status=400)

        # 生成短信验证码
        sms_code = '%06d' % randint(0, 999999)
        print(sms_code)

        # 保存短信验证码
        pl = conn.pipeline()
        pl.setex('sms_%s' % mobile, 300, sms_code)
        pl.setex('sms_flag_%s' % mobile, 60, 1)
        pl.execute()  # 发送redis执行命令

        # 发送短信
        # ccp=CCP()
        # ccp.send_template_sms(mobile,[sms_code,'5'],1)
        send_sms_code.delay(mobile, sms_code)

        # 返回结果
        return Response({'message': 'ok'})

在代码中进行判断,如果频繁发送,返回请求过于频繁

判断用户名、手机号是否存在,通过用户名、手机号的数量来进行判断。如果存在显示存在,如果不存在显示不存在

CORS跨域请求

首先安装

pip install django-cors-headers

在添加应用

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

中间层设置

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...
]

添加白名单

# CORS
CORS_ORIGIN_WHITELIST = (
    '127.0.0.1:8080',
    'localhost:8080',
    'www.meiduo.site:8080',
    'api.meiduo.site:8000'
)
CORS_ALLOW_CREDENTIALS = True  # 允许携带cookie

凡是出现在白名单中的域名,都可以访问后端接口
CORS_ALLOW_CREDENTIALS指明在跨域访问中,后端是否支持对cookie的操作。

密码加密使用set_password()对密码进行加密,还可以使用管理器方法进行加密

    def create(self, validated_data):

        del validated_data['sms_code']
        del validated_data['password2']
        del validated_data['allow']

        # user=super().create(validated_data)
        #
        # # 密码加密
        # user.set_password(validated_data['password'])
        # user.save()
        # 管理器方法 保存用户
        user = User.objects.create_user(username=validated_data['username'], mobile=validated_data['mobile'],
                                        password=validated_data['password'])

        # 生成jwttoken
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        # d对user对象添加token属性字段
        user.token = token

        return user

登录需要状态保持
之前进行状态保持是使用session来记录的,在Django中使用token来记录,

Django中session的使用

  • session是存储在服务器中的,如果数量一旦增加,会增大服务器的开销,占用服务器存储资源,
  • 还有一个问题,如果两台服务器,访问另一台服务器时,另一台服务器不存在用户信息,那么就会存在获取不到用户信息情况,这样就无法返回用户信息。
  • 多个服务器搭建时,如果使用 session这种新式,可能其他服务器判断不了这个session有没有存储过,因为是两台完全不一样的服务器。可能存储在这台服务器,也可能存在另一台服务器上,这样就会导致获取不到数据,拓展性不好。
  • 还有session是基于cookie的,可能会有人获取到cookie值,从而进行跨站请求伪造
    Django知识点回顾_第3张图片

Json Web Token认证机制
JWT(Json Web Token):一种在Web应用中安全传递信息的规范

  • 将获取到的数据进行加密,得到一个token值(加密后的随机字符串)
  • 前端接收到token值之后,将token值(将加密后的随机字符串保存,服务器不保存)保存在storage中
  • 保存在storage避免了CSRF跨站攻击的问题,等到下次再次发起请求,携带的就是token的字符串数据,后端对其进行解密操作,加密和解密使用同一种方法,解密后获取用户信息,获取到用户信息进行返回。
  • 可以解决多台服务器之间数据请求的问题,应为服务器运行的是同一套代码,那么就可以用同一套代码对数据进行解密对token进行解密,解密后就可以得到用户信息,就可以进行相应的操作。
  • token数据是通过请求头部的方式
一般是在请求头里加入Authorization,并加上Bearer标注:

fetch('api/user/1', {
  headers: {
    'Authorization': 'Bearer ' + token
  }
})

Django知识点回顾_第4张图片

JWT构成

  1. 有三部分构成
  2. 第一部分头部(header)
  3. 第二部分载荷(payload)
  4. 第三部分签证(signature).
写入session。 

request.session['name']=python

获取session数据

Request.session.get('name')

session在服务器中保存形式。保存在redis中

以hash 类型进行保存

保存的形式是session的ID,session的ID实际上是一个随机字符串,随机字符串作为key值Ajshdjka123123:键值对{'name':'python'}

浏览器中保存形式。cookie
保存形式是键值对的形式保存
Sesssionid(键是sessionID):Ajshdjka123123(对应Redis中保存的key值)

用户部分

  1. 注册
  2. 登录
  3. 个人信息
  4. 收货地址
  5. 修改密码

用户注册接口:
1、短信验证接口
2、手机号判断是否存在
3、验证用户是否存在
4、验证两次密码输入是否相同
5、判断是否同意协议
6、保存用户注册信息

1、短信验证码

  • 借助第三方平台容联云通讯实现发送短信功能

  • 生成短信验证码

  • 发送短信验证码

  • 检查是否在60秒内有发送验证码记录

  • 通过celery进行异步发送短信

  • 校验短信验证码

  • 验证后通过

  • 前后端分离需要考虑跨域问题,使用了CORS 来解决跨域问题,在文件中配置访问的白名单实现跨域访问功能

  • celery实现异步发送短信,在发送短信过程中可能会出现等待时间过长(阻塞函数同时调用导致)、或者频繁发送短信的可能,这时候我们需要借助基于python开发的celery分布式任务队列的框架,来提高用户体验

  • 记录用户注册或登录状态,我们不在使用session认证机制,而是采用了JWT(Json Web Token认证机制)认证机制,因为session是基于cookie来实现用户验证,cookie如果被截获,容易造成跨域请求伪造,而session又是存储在内存中,这样如果用户量增加会导致独立服务器无法承载更多的用户,如果使用token认证机制,就可以在请求时携带一个服务端提供的token值进行验证

  • JWT的构成
    第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).

  • 前端保存token
    sessionStorage 浏览器关闭即失效
    localStorage 长期有效

账号登录

  • 验证用户名和密码,
  • 验证成功后,为用户签发JWT,
  • 前端将签发的JWT保存下来。
    第三方账号登录(QQ)
    介入QQ登录的接口实现,QQ登录通过参考QQ开发文档,来实现

你可能感兴趣的:(Django)