django缓存和跨域解决和短信验证码的使用
缓存
在实际项目中,存在大量的数据检索,比如我们刷微博的时候,刚开始加载速度慢一点,然后第一次加载完毕之后,如果你此时的手机没有网络,但是你发现你的微博还是可以照样刷,但是刷到一定的页面就走不动了,那么为什么你在刚开始没有网络的时候还可以接着刷呢?这就是用到了缓存,在你第一次加载的时候,就去数据库中将数据查出来,然后直接缓存到你的移动端,那么我们现在要做的就是将数据从数据库中查出来,然后缓存到内存中,下次来请求的时候,直接去缓存中获取,就不用走数据库了,缓解我的数据库的压力,具体书写如下
views中的书写
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.response import Response
from app01 import models
from app01 import seria
from app01 import auth
from django.views.decorators.cache import cache_page
import uuid
from django.core.cache import cache
import time # Create your views here. class Author(APIView):
# 只有认证了才可以看
# authentication_classes = []
# permission_classes = []
# throttle_classes = [] # 返回了所有的图书 def get(self, request):
author_list = models.User.objects.all()
# 进行序列化
user_ser = seria.UserSerializer(instance=author_list, many=True)
return Response(user_ser.data) class Login(APIView):
authentication_classes = []
permission_classes = []
throttle_classes = []
def post(self, request):
back_dic = {'code': 100, 'msg': ''}
username = request.data.get('username')
password = request.data.get('password')
user_type = request.data.get('user_type')
try:
user_obj = models.User.objects.filter(name=username, pwd=password, user_type=user_type).get()
token = uuid.uuid4()
# 添加到了数据库
models.Token.objects.update_or_create(user=user_obj, defaults={'token': token})
# 添加到缓存
back_dic['msg'] = '登录成功'
back_dic['token'] = token
cache.set(token, user_obj.pk, 300)
# print(cache.get(token)) except AuthenticationFailed as e:
back_dic['code'] = 101
back_dic['msg'] = '用户名或者密码错误'
except Exception as e:
back_dic['code'] = 102
back_dic['msg'] = '未知错误'
return Response(back_dic) # 测试 def test(request):
print(1111)
return HttpResponse('test ok') @cache_page(5)
def index(request):
ctime = time.time()
author_list = models.User.objects.all()
return render(request, 'index.html', locals())
Views
写完之后,我们需要在认证中添加和认证
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.throttling import SimpleRateThrottle
from app01 import models
from django.core.cache import cache
from rest_framework.exceptions import AuthenticationFailed class Authentications(BaseAuthentication):
def authenticate(self, request):
# print(request.META)
token = request.META.get('HTTP_TOKEN')
# 能取到说明是通过了
user_pk = cache.get(token)
if user_pk:
user_obj = models.User.objects.filter(pk=user_pk).first()
# 返回的必须是一个元组
return user_obj, token
token_obj = models.Token.objects.filter(token=token).first()
# 说明是一个用户
if token_obj:
cache.set(token, token_obj.pk, 300)
return token_obj.user, token_obj
else:
raise AuthenticationFailed('您还没有登录呢!') class Permissions(BasePermission): def has_permission(self, request, view):
if request.user.user_type == 1:
return True
else:
return False class Throtters(SimpleRateThrottle):
scope = 'three' def get_cache_key(self, request, view):
return self.get_ident(request)
认证
模板中实现局部缓存的方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
{# 单页面缓存 #}
{# 当有局部缓存的时候,需要将原来的装饰器的缓存注释掉 #}
<p>{{ ctime }}</p>
<ul>
{% for author in author_list %}
<li>{{ author.name }}</li>
{% endfor %} </ul>
{# 让他变成局部的缓存 #}
{% load cache %}
{% cache 1 'test' %}
<p>{{ ctime }}</p>
{% endcache %} {% cache 2 'aaa' %}
<p>{{ ctime }}</p>
{% endcache %}
<button id="btn">提交</button>
</body>
<script>
$('#btn').click(function () {
$.ajax({
url:'http://127.0.0.1:8001/test/',
type:'post',
data:{'name': 'egon'},
contentType:'application/json',
success:function (data) {
alert(123);
console.log(data)
}
})
})
</script>
</html>
html展示
模型表的展示
from django.db import models
from django.contrib import auth # Create your models here. class User(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=64)
user_type = models.IntegerField(choices=((1, '超级管理员'), (2, '普通管理员'), (3, '普通用户')), default=3) class Token(models.Model):
user = models.OneToOneField(to='User')
token = models.CharField(max_length=64)
models
在settings中做一些缓存的配置
MIDDLEWARE = [
# 'app01.middlewares.MiddleToken',
# 'django.middleware.cache.UpdateCacheMiddleware', # 重写了process_response的方法
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# 'django.middleware.cache.FetchFromCacheMiddleware' # 重写了process_request的方法
]
# 全站的只是配置了存的方式,但是没有时间的限制,所以要配置超时时间 如果单页面配置了那就以单页面为准
# CACHE_MIDDLEWARE_SECONDS = 10 # 配置缓存 文件存储的形式
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', # 指定缓存使用的引擎
'LOCATION': 'D:\mcc\cache', # 指定缓存的路径
'TIMEOUT': 300, # 缓存超时时间(默认为300秒,None表示永不过期)
'OPTIONS': {
'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
}
}
}
然后就可以简单的实现缓存了,但是实际中,我们缓存也是有一个数据库的,我们一般都使用的是redis数据库,这个详细请看上一篇博客,具体项目中运用,我这里使用的是采用短信验证码登录之后将数据放到缓存中
class SMSAPIView(APIView):
'''
1.用户不能连续发多次的短信,得有一个频率的校验-为钱为防爬
'''
throttle_classes = [SMSSimpleRateThrottle]
def get(self, request, *args, **kwargs):
mobile = request.query_params.get('mobile')
# 字段必须的
if not mobile:
return Response({
'status': 2,
'msg': 'mobile参数是必须的'
})
# 后台要多mobile数据进行安全校验
if not re.match(r'^1[3-9]\d{9}$', mobile):
return Response({
'status': 2,
'msg': '手机号有误'
})
# # 生成随机的验证码
code = ''
for i in range(6):
code += str(random.randint(0, 9))
# redis 存储
cache.set(mobile, code, constat.SMS_EXPIRE_TIME)
# 调用短信第三方发送短信
result = send_sms('176****8046', (code, constat.SMS_EXPIRE_TIME), 1)
if not result:
return Response({
'status': 1,
'result': '短信发送失败'
})
return Response({
'status': 0,
'result': '短信发送成功'
})
获取的时候可以直接get就好。
跨域问题
什么是跨域? HTTP,域名,端口有一个不同就是跨域,是因为浏览器的同源策略导致这种问题的出现
解决方式一
新建一个django项目,用当前项目的ajax向新项目发送请求
<script>
$('#btn').click(function () {
$.ajax({
url:'http://127.0.0.1:8001/test/',
type:'post',
data:{'name': 'egon'},
contentType:'application/json',
success:function (data) {
alert(123);
console.log(data)
}
})
})
</script>
测试的视图函数
def test(request):
# print('1111')
# print(request.META.get('HTTP_ORIGIN'), type(request.META.get('HTTP_ORIGIN')))
# Access-Control-Allow-Origin
import json
# print(111)
obj = HttpResponse(json.dumps({'name': 'lqz', 'age': 32}))
# * 就是全部都可以匹配
# obj['Access-Control-Allow-Origin'] = '*'
# 单个匹配
return obj
test
然后,再打印的时候发现我们是收到了这个请求,但是发的时候被浏览器阻拦了,那我们就要再新项目中允许别的地址给我发送请求,那么这个方法就是要在回去的时候允许,回去的时候走的方法是process_response,那我们就重写这个方法
from django.utils.deprecation import MiddlewareMixin class Middle(MiddlewareMixin): def process_response(self, request, response):
if request.method == 'OPTIONS':
# Content-Type
response['Access-Control-Allow-Headers'] = 'Content-Type'
# obj['Access-Control-Allow-Headers'] = 'Content_Type'
http = request.META.get('HTTP_ORIGIN')
num = http.split(':')[-1]
# print(http)
#
if num in ['', '', '', '', '', '']:
# print(111)
# print('222', http)
response['Access-Control-Allow-Origin'] = http
return response
中间件
这样子就做到了跨域问题的解决
解决方式二
调用别人写好的库,然后只需要配置几个参数就好
下载
pip install django-cors-headers
settings中配置
app中注册
INSTALLED_APPS=[
'corsheaders',] # 允许跨域源,但是由于是所有的都允许,后面什么第三方的网站都可以拿到我的数据
# 所以要改成False
CORS_ORIGIN_ALLOW_ALL = False # 设置白名单允许部分跨域
CORS_ORIGIN_WHITELIST = [
# 记住是自己的前端,要携带端口
'http://127.0.0.1:8080',
# 一般就是浏览器那里显示什么,这里就是什么
# 'http://localhost:8080'
]
之后我们访问的时候就可以了
短信验证码
我们现在在登录一个网站的时候,大多数人都会采用电话号码登录,然后获得验证码的方式进行使用,我们在项目中也采用了这种方式,然后我使用的是容联云通讯
使用步骤如下
1.直接百度搜索容联云通讯,进行注册
2.注册成功后会给你送免费使用额度
3.查看短信接口
然后我们可以直接去查看短信接口的书写,看完之后如果不懂就看demo,最好的例子
4.下载demo
5.配置修改
将sdk中的两个文件拷贝到我们的项目中,然后修改一些东西,因为这里只支持python2.7,所以要做一些修改
1.导包的地方
from hashlib import md5
import base64
import datetime
from urllib import request as urllib2
import json
from .xmltojson import xmltojson
2.异常捕获的地方
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {'': '网络错误'}
3.int和str
4.base64
5.端口
具体的我上面没有写完,我只是列出了大概需要改的地方
6.我们使用的时候还要自己新建一个文件,用来重写他的发送短信验证码的方法
from .CCPRestSDK import REST
from django.conf import settings
# 注:在配置文件dev中完成四个配置信息
# 说明:主账号,登陆云通讯网站后,可在"控制台-应用"中看到开发者主账号ACCOUNT SID
_accountSid = settings.SMS_ACCOUNTSID
# 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
_accountToken = settings.SMS_ACCOUNTTOKEN
# 说明:请使用管理控制台首页的APPID或自己创建应用的APPID
_appId = settings.SMS_APPID
# 说明:请求地址,生产环境配置成app.cloopen.com,开发环境配置成sandboxapp.cloopen.com
_serverIP = settings.SMS_SERVERIP # 说明:请求端口 ,生产环境为8883
_serverPort = ""
# 说明:REST API版本号保持不变
_softVersion = '2013-12-26' def send_sms(mobile, code_expire_tuple, temp_id):
# 配置
rest = REST(_serverIP, _serverPort, _softVersion)
rest.setAccount(_accountSid, _accountToken)
rest.setAppId(_appId)
# 发送
result = rest.sendTemplateSMS(mobile, code_expire_tuple, temp_id)
# 结果:信息成功发生,结果字典result中 statuCode 字段为 "000000"
if result.get("statusCode") == "":
return True # 表示发送短信成功
else:
return False # 表示发送失败
7.去settings中配置
# # 短信的配置 荣联云通信配置
SMS_ACCOUNTSID = '你的accountsid'
SMS_ACCOUNTTOKEN = '你的token'
SMS_APPID = '如果是测试账号,就是未上线,公司的就是上线'
SMS_SERVERIP = 'sandboxapp.cloopen.com'
8.测试
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffyapi.settings.dev')
import django
django.setup() from luffyapi.libs.yuntongxun import send_sms import random def get_code():
code = ""
for i in range(6):
code += str(random.randint(0, 9))
return code code = get_code()
print(code)
result = send_sms('你添加的测试手机号', (code, 5), 1)
print(result)
现在就可以正常使用了
短信验证码的频率校验
class SMSAPIView(APIView):
'''
1.用户不能连续发多次的短信
'''
throttle_classes = [SMSSimpleRateThrottle]
def get(self, request, *args, **kwargs):
mobile = request.query_params.get('mobile')
# 字段必须的
if not mobile:
return Response({
'status': 2,
'msg': 'mobile参数是必须的'
})
# 后台要多mobile数据进行安全校验
if not re.match(r'^1[3-9]\d{9}$', mobile):
return Response({
'status': 2,
'msg': '手机号有误'
})
# # 生成随机的验证码
code = ''
for i in range(6):
code += str(random.randint(0, 9))
# redis 存储
cache.set(mobile, code, constat.SMS_EXPIRE_TIME)
# 调用短信第三方发送短信
result = send_sms('', (code, constat.SMS_EXPIRE_TIME), 1)
if not result:
return Response({
'status': 1,
'result': '短信发送失败'
})
return Response({
'status': 0,
'result': '短信发送成功'
})
短信验证码的登录
class LoginMobileAPIView(APIView):
def post(self, request, *args, **kwargs):
mobile = request.data.get('mobile')
code = request.data.get('code')
# 从redis中取出我们上面设置的验证码
old_code = cache.get(mobile)
if not old_code:
return Response({
'msg': '验证码失效'
})
if old_code != code:
return Response({
'msg': '验证码错误'
})
# 校验用户的手机号是否合法
try:
user = User.objects.get(mobile=mobile)
return Response({
'status': 0,
'msg': '登录成功',
'token': get_jwt_token(user),
'user': UserModelSerializer(user).data
})
except:
return Response({
'msg': '手机号还没有注册'
})
短信验证码的注册
class RegisterMobileAPIView(APIView):
def post(self, request, *args, **kwargs):
mobile = request.data.get('mobile')
password = request.data.get('password')
code = request.data.get('code')
old_code = cache.get(mobile)
if not old_code:
return Response({
'msg': '验证码失效'
})
if old_code != code:
return Response({
'msg': '验证码错误'
})
try:
User.objects.get(mobile=mobile)
return Response({
'status': 1,
'msg': '用户已存在'
})
except:
result = User.objects.create_user(mobile=mobile, password=password, username=mobile)
if result:
return Response({
'status': 0,
'msg': '注册成功'
})
else:
return Response({
'status': 1,
'msg': '注册失败'
})
django缓存和跨域解决和短信验证码的使用的更多相关文章
- 版本控制,django缓存,跨域问题解决
复习 分页: 1. 简单分页 2. 偏移分页 3. 加密分页 解析器:客户处理前端提交来的数据 urlencode: body体中的数据格式: key=value& formdata编码:为区 ...
- Django商城项目笔记No.5用户部分-注册接口-短信验证码
Django商城项目笔记No.4用户部分-注册接口-短信验证码 短信验证码也保存在redis里(sms_code_15101234567) 在views中新增SMSCodeView类视图,并且写出步骤 ...
- 解决Django本地接口不能跨域访问的问题
1.安装django-cors-headers模块: pip install django-cors-headers 2.插入Django的APP配置中: # 修改settings.py中的INSTA ...
- django 前端请求跨域问题解决
django 前端请求跨域问题解决 笔者之前在做django-restful-api开发的时候,在前端请求页面发送请求的时候直接出现301,域名重定向的问题,经过一番查阅资料,终于得到了非常完美的解决 ...
- Django框架 之 跨域请求伪造
Django框架 之 跨域请求伪造 浏览目录 同源策略与Jsonp 同源策略 Jsonp jQuery对JSONP的实现 CORS 简介 两种请求 同源策略与Jsonp 同源策略 同源策略(Same ...
- django 12天(跨域,文件上传,下载,cookie,session)
django 12天(跨域,文件上传,下载) 跨域 什么是跨域 1.协议不同 2.端口不同 3.主机不同 如何解决跨域 1.安装django-cors-headers模块 2.在settings.py ...
- JavaScript跨域解决办法
在找到跨域解决办法之前,我们要先弄清楚一些基本概念 什么是跨域? 什么是“同源策略”? 跨文档消息通信 & 跨域请求数据 主域相同而子域不同 不同域名的跨域访问 什么是跨域? 简单地理解就是因 ...
- JAVA联调接口跨域解决办法
JAVA联调接口跨域解决办法 第一种代码: HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus. ...
- [转]vue跨域解决方法
vue跨域解决方法 vue项目中,前端与后台进行数据请求或者提交的时候,如果后台没有设置跨域,前端本地调试代码的时候就会报“No 'Access-Control-Allow-Origin' hea ...
随机推荐
- Python---2文本编辑器
1.介绍 在Python的交互式命令行写程序,好处是一下就能得到结果,坏处是没法保存,下次还想运行的时候,还得再敲一遍. 所以,实际开发的时候,我们总是使用一个文本编辑器来写代码,写完了,保存为一个文 ...
- const define static extern
const const意味着"只读",欲阻止一个变量被改变,可以使用const关键字 const仅仅用来修饰右边的变量(基本数据变量p,指针变量*p) define #define ...
- linux记录每次登陆的历史命令
编辑/etc/profile,增加如下代码 #Record history operation USER_IP=`>/dev/null |awk '{print $NF}' |sed -e 's ...
- concurrent包分析之Executor框架
文章目录 线程生命周期的开销:线程比较少的情况使用new Thread(task)无多大影响,但是如果涉及到线程比较多的情况,应用的性能就会受到影响,如果jdbc创建连接一样,new Thead创建线 ...
- Alberto Del Bimbo:为什么说研究员要有想象力?
Del Bimbo:为什么说研究员要有想象力?" title="Alberto Del Bimbo:为什么说研究员要有想象力?"> 说到科研,与日本式的&q ...
- Redis(1)——5种基本数据结构
一.Redis 简介 "Redis is an open source (BSD licensed), in-memory data structure store, used as a d ...
- log4p踩坑总结
log4p可以方便的打印格式化日志,在实际应用时,因没有好好理解官网中的配置文件,导致出错了几次. 现总结如下: 1. 安装 pip3 install log4p 2. 查看配置说明,请参考https ...
- AI入门之KNN算法学习
一.什么是KNN算法 kNN(k-NearestNeighbor),也就是k最近邻算法.顾名思义,所谓K最近邻,就是k个最近的邻居的意思.也就是在数据集中,认为每个样本可以用离他最距离近的k个邻居来代 ...
- Java - 常见的算法
二分法查找 private static int binarySearch(int[] list,int target) { ; ; //直到low>high时还没找到关键字就结束查找,返回-1 ...
- 利用GitHub制作在线炫酷简历
首先我们先体验一下炫酷简历.然后决定我们要不要使用. https://jessezhao1990.github.... 如何使用本项目部署你自己的在线简历 1. 书写简历 在src文件夹里面有个con ...