zoukankan      html  css  js  c++  java
  • 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',
    ]
  • 相关阅读:
    express实现前后端通信上传图片,存储数据库(mysql)傻瓜教程(二)
    express实现前后端通信上传图片,存储数据库(mysql)傻瓜教程(一)
    [转载] 在阿里做了五年技术主管,我有话想说
    阿里云RDS MySql还原到本地Linux/Centos
    如何领域驱动设计?-实践感悟&总结分享
    jira + confluence 安装和破解
    RabbitMQ安装和配置
    [转]技术路线的选择重要但不具有决定性
    .Net core2.0日志组件Log4net、Nlog简单性能测试
    在微服务中使用领域事件
  • 原文地址:https://www.cnblogs.com/lakei/p/11153648.html
Copyright © 2011-2022 走看看