缓存

  在实际项目中,存在大量的数据检索,比如我们刷微博的时候,刚开始加载速度慢一点,然后第一次加载完毕之后,如果你此时的手机没有网络,但是你发现你的微博还是可以照样刷,但是刷到一定的页面就走不动了,那么为什么你在刚开始没有网络的时候还可以接着刷呢?这就是用到了缓存,在你第一次加载的时候,就去数据库中将数据查出来,然后直接缓存到你的移动端,那么我们现在要做的就是将数据从数据库中查出来,然后缓存到内存中,下次来请求的时候,直接去缓存中获取,就不用走数据库了,缓解我的数据库的压力,具体书写如下

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缓存和跨域解决和短信验证码的使用的更多相关文章

  1. 版本控制,django缓存,跨域问题解决

    复习 分页: 1. 简单分页 2. 偏移分页 3. 加密分页 解析器:客户处理前端提交来的数据 urlencode: body体中的数据格式: key=value& formdata编码:为区 ...

  2. Django商城项目笔记No.5用户部分-注册接口-短信验证码

    Django商城项目笔记No.4用户部分-注册接口-短信验证码 短信验证码也保存在redis里(sms_code_15101234567) 在views中新增SMSCodeView类视图,并且写出步骤 ...

  3. 解决Django本地接口不能跨域访问的问题

    1.安装django-cors-headers模块: pip install django-cors-headers 2.插入Django的APP配置中: # 修改settings.py中的INSTA ...

  4. django 前端请求跨域问题解决

    django 前端请求跨域问题解决 笔者之前在做django-restful-api开发的时候,在前端请求页面发送请求的时候直接出现301,域名重定向的问题,经过一番查阅资料,终于得到了非常完美的解决 ...

  5. Django框架 之 跨域请求伪造

    Django框架 之 跨域请求伪造 浏览目录 同源策略与Jsonp 同源策略 Jsonp jQuery对JSONP的实现 CORS 简介 两种请求 同源策略与Jsonp 同源策略 同源策略(Same ...

  6. django 12天(跨域,文件上传,下载,cookie,session)

    django 12天(跨域,文件上传,下载) 跨域 什么是跨域 1.协议不同 2.端口不同 3.主机不同 如何解决跨域 1.安装django-cors-headers模块 2.在settings.py ...

  7. JavaScript跨域解决办法

    在找到跨域解决办法之前,我们要先弄清楚一些基本概念 什么是跨域? 什么是“同源策略”? 跨文档消息通信 & 跨域请求数据 主域相同而子域不同 不同域名的跨域访问 什么是跨域? 简单地理解就是因 ...

  8. JAVA联调接口跨域解决办法

    JAVA联调接口跨域解决办法 第一种代码: HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus. ...

  9. [转]vue跨域解决方法

      vue跨域解决方法 vue项目中,前端与后台进行数据请求或者提交的时候,如果后台没有设置跨域,前端本地调试代码的时候就会报“No 'Access-Control-Allow-Origin' hea ...

随机推荐

  1. Soldier and Badges

    题目链接:https://vjudge.net/problem/CodeForces-546B AC代码: #include<iostream> #include<algorithm ...

  2. AndroidManifest.xml文件详解

    本文为安全专家李洋的最新一篇专栏文章<AndroidManifest.xml文件详解>.AndroidManifest.xml是一个跟安全相关的配置文件,该配置文件是Android安全保障 ...

  3. Linux USB 鼠标驱动程序详解(转)

    Linux USB 鼠标驱动程序详解 USB 总线引出两个重要的链表!一个 USB 总线引出两个重要的链表,一个为 USB 设备链表,一个为 USB 驱动链表.设备链表包含各种系统中的 USB 设备以 ...

  4. C语言职工信息管理系统

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  5. IP 转发分组的流程

    IP 转发分组的流程 数据路由:路由器在不同网段转发数据包: 网络畅通的条件:数据包能去能回: 从源网络发出时,沿途的每一个路由器必须知道到目标网络下一跳给哪个接口: 从目标网络返回时,沿途的每一个路 ...

  6. 成长日记(2) Java面向对象

    本篇主要是记录自己在学习路上的笔记,如果有哪里记错了请大家直接指出 面向对象的概念 *人为抽象的一种编程模型 *面向过程 代码集中 难以维护 *类:对事物 算法 逻辑 概念等的抽象 理解成 模板 图纸 ...

  7. pycharm 关于模块安装出现的“[error] Microsoft Visual C++ 14.0 is required” 解决办法

    刚才正准备对pycharm进行一番操作的时候,噔  噔磴噔噔 “no module define xxx” ,那我当然要把xxx给搞到pycharm上来啊, 不一会功夫 ,biu~ “[error] ...

  8. sql05

    1.Ado.net Ado.net是一组由微软提供的使用C#操作数据库的类库 2.连接 首先引入: using System.Data.SqlClient; 需要使用连接字符串进行连接 using S ...

  9. HTML常用表单标签

    1.表单元素 <form> HTML 表单用于收集用户输入. 代码示例: <form action="http://xxx.xxx.xxx/xxx.php" me ...

  10. 关于使用layui中的tree的一个坑

    最近几天,因为项目需要,所以自学了下layui,在使用之前就对其比较感兴趣,毕竟封装的东西也不错(个人见解),在接触到layui之后,现在有个需要就是将部门做成tree的样子,开始觉得不怎么难,毕竟都 ...