django中的缓存 跨域问题(同源策略)

 

 

django缓存机制

在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面.

当一个网站的用户访问量很大的时候,每一次的的后台操作,都会消耗很多的服务端资源,所以必须使用缓存来减轻后端服务器的压力.

缓存是将一些常用的数据保存内存或者memcache中,在一定的时间内有人来访问这些数据时,则不再去执行数据库及渲染等操作,而是直接从内存或memcache的缓存中去取得数据,然后返回给用户.

 

django中的6中缓存方式

开发调试缓存  没有缓存

内存缓存

文件缓存

数据库缓存

缓存到redis

Memcache缓存(使用python-memcache模块)

Memcache缓存(使用pylibmc模块)

经常使用的有文件缓存和Mencache缓存

 

缓存配置

settings中配置缓存位置的配置(settings中配置,BACKEND不同,缓存的位置不同) 必须要配置

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

    }
}

 

缓存粒度

  全站缓存

  单页面缓存

  局部缓存

 

 

文件缓存(把缓存数据存储在文件中)

使用:

  settings文件,把cache配置进去

单页面缓存:在视图函数上加一个装饰器

from django.views.decorators.cache import cache_page

@cache_page(5)    5 代表缓存时间

 

例子

fbv加局部缓存装饰器

import time
from django.views.decorators.cache import cache_page  局部缓存装饰器
# #局部缓存
@cache_page(5)
def index(request):
    ctime = time.time()
    return render(request,'index.html',{'ctime':ctime})

cbv加装饰器

from django.utils.decorators import method_decorator

django的bug,不能直接对类进行装饰,必须使用 method_decorator,把装饰器当作参数传进去。

@method_decorator(wrapper, name="post")

#PS:CBV中添加装饰器

def wrapper(func):

    def inner(*args,**kwargs):

        return func(*args,**kwargs)

    return inner
#1.指定方法上添加装饰器

class Foo(View):

    @method_decorator(wrapper)

    def get(self,request):

        pass

    def post(self,request):

        pass
#2.在类上添加

@method_decorator(wrapper,name='dispatch')

class Foo(View):

    def get(self,request):
        pass

    def post(self,request):

        pass

 

 

局部缓存

{% load cache %}

{% cache 5 'test'}   <!--第一个参数表示缓存时间,第二个参数是key值(取缓存的时候,需要根据key值取)-->

    当前时间:{{ ctime }}
{% endcache %}

视图函数

from django.views.decorators.cache import cache_page
import time
from .models import *
def index(request):
     cttime=time.time()      #获取当前时间
     bookList=Book.objects.all()
     return render(request,"index.html",locals())

 

全站缓存

既然是全站缓存,当然要使用Django中的中间件.

用户的请求通过中间件,经过一系列的认证等操作,如果请求的内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户

当返回给用户之前,判断缓存中是否已经存在,如果不存在,则UpdateCacheMiddleware会将缓存保存至Django的缓存之中,以实现全站缓存

#缓存整个站点,是最简单的缓存方法
#在MIDDLEWARE_CLASSES 中加入 "update"和"fetch"中间件

MIDDLEWARE_CLASSES = (
    ‘django.middleware.cache.UpdateCacheMiddleware’, #第一
    'django.middleware.common.CommonMiddleware',
    ‘django.middleware.cache.FetchFromCacheMiddleware’, #最后
)

#"update"必须配置在第一个
#"fetch" 必须配置在最后一个

需要改settings.py配置文件

MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',    #全局控制 内部有process_response  响应HTTPResponse中设置几个headers
    '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 用来缓存通过GET和HEAD方法获取的状态码为200的响应
]

CACHE_MIDDLEWARE_SECONDS=5      #去局配置缓存 过期时间

视图函数

import time

def index(request):
    ctime = time.time()
    return render(request,'index.html',{'time':ctime})

模板

{{ time }}

其余代码不变,刷新浏览器5秒,页面上的时间变化一次,这样就实现了全站缓存

 

高级用法

  前后端分离项目 

  from django.core.cache import cache  

  cache.set  cache.get

设置值跟取值:
         cache.set('test_data',{'name':'lqz','age':18},5)
         cache.get('test_data')

 

 

  自定义Response对response再次进行封装

from rest_framework.response import Response

class MyResponse():
    def __init__(self):
        self.code = 100
        self.msg = None

    def get_response(self):
        return Response(self.__dict__)  #返回名称空间

使用

from app01.utils import  MyResponse #自定义Response封装
from rest_framework.views import APIView
class Test(APIView):
    def get(self,request):
        response = MyResponse()
        response.data = {'name':'llxbl','age':18}
        response.code = 200
        response.msg = '查询成功'
        return response.get_response()

 

开发调试(此模式为开发调试使用,实例上不执行任何操作)

settings配置

CACHES = {
 'default': {
  'BACKEND': 'django.core.cache.backends.dummy.DummyCache',  # 缓存后台使用的引擎
  'TIMEOUT': 300,            # 缓存超时时间(默认300秒,None表示永不过期,0表示立即过期)
  'OPTIONS':{
   'MAX_ENTRIES': 300,          # 最大缓存记录的数量(默认300)
   'CULL_FREQUENCY': 3,          # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  },
 }
}
View Code

第二种

# 此为开始调试用,实际内部不做任何操作
# 配置:
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎
            'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
            'OPTIONS':{
                'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
            },
            'KEY_PREFIX': '',                                             # 缓存key的前缀(默认空)
            'VERSION': 1,                                                 # 缓存key的版本(默认1)
            'KEY_FUNCTION': 函数名                                         # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
        }
    }


# 自定义key
def default_key_func(key, key_prefix, version):
    """
    Default function to generate keys.

    Constructs the key used by all other methods. By default it prepends
    the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
    function with custom key making behavior.
    """
    return '%s:%s:%s' % (key_prefix, version, key)

def get_key_func(key_func):
    """
    Function to decide which key function to use.

    Defaults to ``default_key_func``.
    """
    if key_func is not None:
        if callable(key_func):
            return key_func
        else:
            return import_string(key_func)
    return default_key_func
View Code

 

内存缓存(将缓存内容保存至内存区域中)

settings配置

CACHES = {
 'default': {
  'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',  # 指定缓存使用的引擎
  'LOCATION': 'unique-snowflake',         # 写在内存中的变量的唯一值 
  'TIMEOUT':300,             # 缓存超时时间(默认为300秒,None表示永不过期)
  'OPTIONS':{
   'MAX_ENTRIES': 300,           # 最大缓存记录的数量(默认300)
   'CULL_FREQUENCY': 3,          # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  }  
 }
}
View Code

 

数据库缓存(把缓存数据存储在数据库中)

settings配置

CACHES = {
 'default': {
  'BACKEND': 'django.core.cache.backends.db.DatabaseCache',  # 指定缓存使用的引擎
  'LOCATION': 'cache_table',          # 数据库表    
  'OPTIONS':{
   'MAX_ENTRIES': 300,           # 最大缓存记录的数量(默认300)
   'CULL_FREQUENCY': 3,          # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  }  
 }   
}
View Code

# 注创建缓存的数据库表使用的语句:执行创建表命令 python manage.py createcachetable

 

Memcache缓存(使用python-memcached模块连接memcache)

Memcached是Django原生支持的缓存系统.要使用Memcached,需要下载Memcached的支持库python-memcached或pylibmc.

settings.py文件配置

CACHES = {
 'default': {
  'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', # 指定缓存使用的引擎
  'LOCATION': '192.168.10.100:11211',         # 指定Memcache缓存服务器的IP地址和端口
  'OPTIONS':{
   'MAX_ENTRIES': 300,            # 最大缓存记录的数量(默认300)
   'CULL_FREQUENCY': 3,           # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  }
 }
}
View Code

LOCATION也可以配置成如下:

'LOCATION': 'unix:/tmp/memcached.sock',   # 指定局域网内的主机名加socket套接字为Memcache缓存服务器
'LOCATION': [         # 指定一台或多台其他主机ip地址加端口为Memcache缓存服务器
 '192.168.10.100:11211',
 '192.168.10.101:11211',
 '192.168.10.102:11211',
]
View Code

 

第二种

# 此缓存使用python-memcached模块连接memcache

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': 'unix:/tmp/memcached.sock',
    }
}   

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': [
            '172.19.26.240:11211',
            '172.19.26.242:11211',
            # 设置权重,memcache模块做的
            ('172.19.26.240:11211',1)
            ('172.19.26.242:11211',10)
        ]
    }
}
View Code

 

Memcache缓存(使用pylibmc模块连接Memcache)

settings.py文件配置
 CACHES = {
  'default': {
   'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',  # 指定缓存使用的引擎
   'LOCATION':'192.168.10.100:11211',         # 指定本机的11211端口为Memcache缓存服务器
   'OPTIONS':{
    'MAX_ENTRIES': 300,            # 最大缓存记录的数量(默认300)
    'CULL_FREQUENCY': 3,           # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
   },  
  }
 }
View Code

LOCATION也可以配置成如下:

'LOCATION': '/tmp/memcached.sock',  # 指定某个路径为缓存目录
'LOCATION': [       # 分布式缓存,在多台服务器上运行Memcached进程,程序会把多台服务器当作一个单独的缓存,而不会在每台服务器上复制缓存值
 '192.168.10.100:11211',
 '192.168.10.101:11211',
 '192.168.10.102:11211',
]
View Code

Memcached是基于内存的缓存,数据存储在内存中.所以如果服务器死机的话,数据就会丢失,所以Memcached一般与其他缓存配合使用

 

第二种

# 此缓存使用pylibmc模块连接memcache
    
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': '/tmp/memcached.sock',
    }
}   

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': [
            '172.19.26.240:11211',
            '172.19.26.242:11211',
        ]
    }
}
View Code

 

跨域问题(同源策略)

浏览器的:同源策略,浏览器拒绝不是当前域返回的数据

ip地址和端口号都相同才是同一个域

比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据

浏览器上就会报错,个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险

已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8001/SendAjax/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

但是注意,项目2中的访问已经发生了,说明是浏览器对非同源请求返回的结果做了拦截

 

如何解决:

  CORS:跨域资源共享

  简单请求:发一次请求

  非简单请求:非简单请求是发送了两次请求,第一次是预检请求(OPTIONS请求),当预检通过,允许我发请求,再发送真实的请求

  

 简单请求需要满足两大条件

(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

 

 凡是不同时满足上面两个条件,就属于非简单请求。

 浏览器对这两种请求的处理,是不一样的。

* 简单请求和非简单请求的区别?

   简单请求:一次请求
   非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
* 关于“预检”

- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
     => 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
        Access-Control-Request-Method
     => 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
        Access-Control-Request-Headers

 

 

支持跨域,简单请求

服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'

支持跨域,复杂请求

由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。

  • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
  • “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
  $('button').click(function () {
        alert('111');
        $.ajax({
            url:'http://127.0.0.1:8001/index/',
            type:'post',
            contentType:'application/json',
            data:{'name':'lqz'},
            success:function (data) {
                console.log(data)
            }
        })
    })

 

被请求站点

def index(request):

    obj = HttpResponse('11111111')
    if request.method == 'OPTIONS':
    #     #允许它
        obj['Access-Control-Allow-Headers']='Content-Type'
    #     # obj['Access-Control-Allow-Headers'] = '*'
    #
    #
    # # obj['Access-Control-Allow-Origin'] = '*'
    obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000'
    print(obj)
    return obj

 

 

 

 解决跨域问题:(写好一个中间件配置一下)  被请求站点

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-Headers'] = '*'

        # response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000'
        # 允许的请求站点
        response['Access-Control-Allow-Origin'] = '*'
        return response
MIDDLEWARE = [
    'app01.MyMiddle.MyCorsMiddle',  #跨域问题
    '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',
]

 

posted @ 2019-07-08 20:35  读自己  阅读(251)  评论(0编辑  收藏  举报