Django缓存浅谈,token应用,跨域请求

Django中的缓存方式
缓存位置:
缓存到内存中
缓存到数据库中,(一条语句查询出多条数据)
缓存到文件
缓存到redis
缓存位置的配置(在setting中配置,BACKEND不同,缓存的位置不同)

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',  # 指定缓存使用的引擎
        'LOCATION': 'D:\lqz\cache',  # 指定缓存的路径
        'TIMEOUT': 300,  # 缓存超时时间(默认为300秒,None表示永不过期)
        'OPTIONS': {
            'MAX_ENTRIES': 300,  # 最大缓存记录的数量(默认300)
            'CULL_FREQUENCY': 3,  # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        }
    }
}

缓存粒度:
全站缓存注:全站缓存是根据你的路由来区分缓存的位置的
需要以下配置:
settings.py 需要你在通过所有的中间件的校验,然后才能去缓存中取出数据,然后依次返回,返回到中间件的最初然后更新数据(若没有数据到数据库查找数据,更新数据)

settings.py
MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    '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'
]
CACHE_MIDDLEWARE_SECONDS = 2

单页面缓存
注:单页面缓存是根据你的路由来区分缓存的位置的

from django.views.decorators.cache import cache_page
@cache_page(5)
def index(request):
    ctime = time.time()
    return render(request,'index.html',{"ctime":ctime})

局部缓存

{% load cache %}
{% cache 5 "test" %}
<h1>{{ ctime }}</h1>
{% endcache %}

高级用法前后端分离:
代码如下:

from django.core.cache import cache
from rest_framework.views import APIView
from rest_framework.response import Response
class Test(APIView):
    def get(self,request,*args,**kwargs):
        cache.set('test_data',{"name":"wy","age":18},3)
        #若取出来为空说明你超时了
        time.sleep(2)
        x = cache.get("test_data")
        if x:
            print('未超时')
            back_dic = {
                "stat":"未超时"
            }
            return Response(back_dic)
        else:
            print("超时")
            back_dic = {
                "stat": "超时"
            }
            return Response(back_dic)

跨域问题:
-浏览器的:同源策略,浏览器拒绝不是当前域域返回的数据,因为请求了一个资源发现不是我同源的会担心是病毒,所以浏览器不接受,只有你通过CORS跨域资源共享才可以。
-ip地址和端口号都相同才是同一个域
-如何解决:
-CORS:跨域资源共享
-简单请求:发一次请求
-非简单请求:非简单请求是发送了两次请求,第一次是预检请求(OPTIONS请求),当预检通过,允许我发请求,再发送真实的请求。
由于不管你是post还是get请求只要是非简单请求你都需要发送OPTIONS,这样每条非简单的请求都需要发送OPTIONS,我们可以在全局中做了这件事,通过中间件的process_response,为什么是response因为是需要返回给你的浏览器端,是最后返回,然后你需要判断是不是OPTIONS请求,是的化你就设置允许,只要头部加了Content-Type你就需要设置允许:response[“Access-Control-Allow-Headers”] = “Content-Type”,如果不是你还需要设置:response[“Access-Control-Allow-Origin”] = “http://127.0.0.1:8000
最后返回response对象。

from django.contrib.sessions.middleware import SessionMiddleware
from django.utils.deprecation import MiddlewareMixin
class MyCorsMiddle(MiddlewareMixin):
		def process_response(self,request,response):
				if  request.method == "OPTIONS":
						response["Access-Control-Allow-Headers"] = "Content-Type"
				response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8000"
		return response

具体案例:
访问端代码:
urls.py:

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
]

views.py:

from django.shortcuts import render

from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt,name="dispatch")
# Create your views here.
def index(request):
    # if request.method==''

    return render(request,'index.html')

index.html

<!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>
</head>
<body>
<button id="btn">点我</button>
</body>
<script>
    $("#btn").click(function () {
        $.ajax({
            url:'http://127.0.0.1:8080/books/'
            ,type:"post",
            contentType:"application/json",
            success:function (res) {
                console.log(res)
            }
        })
    })
</script>
</html>

另外一端:中间件装饰

from django.contrib.sessions.middleware import SessionMiddleware
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, HttpResponse

class MyMiddle(MiddlewareMixin):
    def process_response(self, request, response):
        if request.method == 'OPTIONS':
            # 请求返回返回头中
            response['Access-Control-Allow-Headers'] = 'Content-Type'
        dat = request.META
        # print(dat)
        orgin = dat.get("HTTP_ORIGIN")
        l = []
        ip, port = orgin.rsplit(":", 1)
        l.append(port)
        if port in ['8002','8003','8004']:
            print(ip, port)

            response['Access-Control-Allow-Origin'] = orgin


        # response['Access-Control-Allow-Origin'] = "http://127.0.0.1:8001"
        print(type(response),response)
        return response

序列化

MySer.py
from rest_framework import serializers
from app01 import models
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"

views.py

from django.shortcuts import render,HttpResponse

# Create your views here.
from rest_framework.views import APIView
from app01.MySer import BookSer
from app01 import models
from rest_framework.response import Response
# from rest_framework.viewsets import ModelViewSet
class Book(APIView):
    #
    def get(self,request,*args,**kwargs):
        print('xxxxxx')
        book_list = models.Book.objects.all()
        bookser = BookSer(instance=book_list,many=True)
        back_dic = {"code":100}
        back_dic['data'] = bookser.data
        return HttpResponse("yy")
    def post(self,request,*args,**kwargs):
        print('post')
        book_list = models.Book.objects.all()
        bookser = BookSer(instance=book_list,many=True)
        back_dic = {"code":100}
        back_dic['data'] = bookser.data
        return HttpResponse("zz")

token应用:
客户端登录成功后,服务器根据客户端的信息制作一个唯一的token值传给浏览器,浏览器下次来访问的时候带着这个token,然后服务端通过自己的算法将token解出来与用户的签名匹配,匹配成功则表示用户是合法用户.
在你项目目录下新建一个用于校验是否登陆过的代码认证代码MyAuth.py

from rest_framework.authentication import BaseAuthentication
from rest_framework.views import APIView
from rest_framework.exceptions import AuthenticationFailed
from app01 import models
from django.core.cache import cache
from django.core.cache import cache
class Auth(BaseAuthentication):
    def authenticate(self, request):
    '''
    首先接收那个头中的数据,接收浏览器端头部的数据都是通过请求request.META.get("HTTP_传入的名字")
    '''
        #传了一个token过来
        print(request.META)
        #获取前端传过来的头信息中的token
        token_get = request.META.get("HTTP_TOKEN")
        #从缓存取出数据token数据,cache(key,value,过期时间)
        token = cache.get(token_get)
        #下方是为了给数据库减压使用的,由于使用缓存中的数据可以减少数据库的访问,若缓存过期了再去数据库中查找。
        if not token:#缓存中没有token,然后就到数据库张找
            token_obj = models.Token.objects.filter(token=token_get)
            if token_obj:
                #反向查询表明小写
                print('超时了')
                return token_obj.first().user,token_get
            else:
                # print('用户名或者密码错误')
                raise AuthenticationFailed("用户名或者密码错误")
                # return False,False
        else:
            print('没有超时')
            token_obj = models.Token.objects.filter(token=token_get)
            return token_obj.first().user, token

视图函数:

from rest_framework.views import APIView
from app01.MyAuth import Auth
import time
import hashlib,pickle
# from
'''
-4 全站缓存
-在setting中配置两个中间件:注意顺序
'django.middleware.cache.UpdateCacheMiddleware',
    。。。。
'django.middleware.cache.FetchFromCacheMiddleware'
'''
from django.core.cache import cache
from app01 import models
def token_produce(v1):
    '''
    :param v1: 用户名
    '''
    #token是由名字与我的时间组合而成的
    md = hashlib.md5()
    md.update(v1.encode("utf-8"))
    return md.hexdigest()


from app01 import MySer
from rest_framework.response import Response
#token 超时时间  与缓存的超时时间
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
#CBV的csrf装饰器,之呢给加在类上,指定dispatch分发方法相当于给所有的都解除了中间件的校验。
@method_decorator(csrf_exempt,name="dispatch")
class Login(APIView):
    def post(self,request,*args,**kwargs):
        print('post')
        name = request.data.get("name")
        password = request.data.get("password")
        user_obj = models.User.objects.filter(name=name,password=password).first()
        print(name,password)
        if user_obj:
            token_str = token_produce(name)
            # va = user_obj.token
            # print("*(**(*(",va,type(va))
            models.Token.objects.update_or_create(token=token_str)
            # print(token)
            # tokenser = MySer.TokenSer(instance=token)
            back_dic = {'token':token_str}
            cache.set(token_str,token_str,600)
            return Response(back_dic)
        else:
            return Response("登录失败")

class Book(APIView):
#图书类,首先要通过验证才能查看图书,因此加了身份认证
    authentication_classes = [Auth, ]
    def get(self,request,*args,**kwargs):
        print('book')
		
        book_list = models.Book.objects.all()
        #序列化主要是为了前端的交互方便,序列化为json,而我的HttpResponse不能序列化queryset对象。
        book_ser = MySer.BookSer(instance=book_list,many=True)
        return Response(book_ser.data)

Myser.py序列化

from rest_framework import serializers
from app01 import models
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"

class TokenSer(serializers.ModelSerializer):
    class Meta:
        model = models.Token
        fields = "__all__"

models.py类:

from django.db import models

# Create your models here.
class User(models.Model):
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    token = models.OneToOneField(to="Token")


class Token(models.Model):
    token = models.CharField(max_length=256)


class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值