一、配置缓存

 
https://www.jb51.net/article/124434.htm

二、缓存全站、页面、局部

 

三、自我控制的简单缓存API
  • API 接口为:django.core.chache
    存接口:cache.set(key, value, time_out)
    取接口:cache.get(key)

django中的低层次缓存API

有些时候,对整个经解析的页面进行缓存并不会给你带来太多好处,事实上可能会过犹不及。
比如说,也许你的站点所包含的一个视图依赖几个费时的查询,每隔一段时间结果就会发生变化。 在这种情况下,使用站点级缓存或者视图级缓存策略所提供的整页缓存并不是最理想的,因为你可能不会想对整个结果进行缓存(因为一些数据经常变化),但你仍然会想对很少变化的部分进行缓存。
针对这样的情况,Django提供了简单低级的缓存API。 你可以通过这个API,以任何你需要的粒度来缓存对象。 你可以对所有能够安全进行 pickle 处理的 Python 对象进行缓存: 字符串、字典和模型对象列表等等。 (查阅 Python 文档可以了解到更多关于 pickling 的信息。)
缓存模块django.core.cache拥有一个自动依据CACHE_BACKEND设置创建的django.core.cache对象。

使用缓存须知:默认调用settings 中的缓存配置
如果取的key不存在默认返回None

cache.get() 接受缺省参数:cache.get('my_key', 'has expired')
不存在将返回:'has expired'

自动删除没有设置超时时间、或者没超时的key
  • cache.delete(key)
     
    可以用 cache.delete() 显式地删除关键字:
     
    cache.delete('a')

也可以使用incr()或者decr()来增加或者减少已经存在的键值。 默认情况下,增加或减少的值是1。可以用参数来制定其他值。 如果尝试增减不存在的键值会抛出ValueError。

>>> cache.set('num', 1)
>>> cache.incr('num')
2
>>> cache.incr('num', 10)
12
>>> cache.decr('num')
11
>>> cache.decr('num', 5)
  • 注意:
     
    incr()/decr()方法不是原子操作。 在支持原子增减的缓存后端上(最著名的是memcached),增减操作才是原子的。 然而,如果后端并不原生支持增减操作,也可以通过取值/更新两步操作来实现。

 

3.2 rest_framework 源码解析
  • rest_framework中节流源码使用的就是django提供的缓存api
    def dispatch(self, request, *args, **kwargs):    
          ...
        self.args = args
        self.kwargs = kwargs
        ##############################################################

        request = self.initialize_request(request, *args, **kwargs)          # 1.封装request

        #封装后的request对象
        #return Request(
        #   request,
        #    parsers=self.get_parsers(),
        #    authenticators=self.get_authenticators(),   #获取认证对象
        #    negotiator=self.get_content_negotiator(),
        #    parser_context=parser_context
        #)

        #############################################################
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
        ##############################################################

            self.initial(request, *args, **kwargs)   #2 初始化认证

        ##############################################################
            ...
        except Exception as exc:
            ...
        return self.response
  • 再看#2 self.initial(request, *args, **kwargs) 初始化各种认证的过程
    def initial(self, request, *args, **kwargs):
        .....

        # Ensure that the incoming request is permitted

        self.perform_authentication(request)           #3.在这儿实现认证

        self.check_permissions(request)             #4.权限检查
 
        self.check_throttles(request)            #5.访问频率控制
  • 重点看#5处,里面循化认证了频率控制:这儿就不贴出#5中的源码了
    直接将循环的类中去查看:from rest_framework.throttling import SimpleRateThrottle
class SimpleRateThrottle(BaseThrottle):
   ...
    #实际是:from django.core.cache import cache as default_cache
    cache = default_cache   #可以看到这儿就是调用django提供的缓存api
     ...
    scope = None #这儿是配置频率,可以到配置文件中去配置,也可以继承类重写:如3/m
    ...


    def get_cache_key(self, request, view):
        """
        必须重写该方法,将缓存的 key返回:常用用户名、IP等做访问频率的控制
        如:
        return request.META.remote_addr() 或者 用户名
        """
        raise NotImplementedError('.get_cache_key() must be overridden')

    def get_rate(self):
        #从配置文件中拿出访问频率
        ...

    def parse_rate(self, rate):
        #解析配置文件中的访问频率文本
        ...

    def allow_request(self, request, view):
        #访问频率的控制,认证
        ...

        if self.rate is None:
            return True

        self.key = self.get_cache_key(request, view)   #从我们重写的方法中拿到缓存key
        if self.key is None:
            return True

        self.history = self.cache.get(self.key, [])    #从缓存中拿出用该key存的数据
        self.now = self.timer()

        ...
        return self.throttle_success()

    def throttle_success(self):
        #认证成功,重新设置缓存
        ...
        self.history.insert(0, self.now)
        self.cache.set(self.key, self.history, self.duration)  #重新设置缓存
        return True

 

3.2.2 总结rest_framework中的频率控制流程,及cache的使用

 

  1. 引入rest_framework: from rest_framework import APIView
    APIView继承了Django中的View 也就是CBV中的View
     
    引入:SimpleThrottle:from rest_framework.throttling import SimpleThrottle
    自己的类继承SimpleThrottle:并重写 get_cache_key(self, request, view)方法,以及scope 访问频率
    如果全局使用就配置到settings.py中:DEFALUT_THROTTLE_CLASSES = [自己的访问频率控制类, ]
    如果局部:就在继承了APIView中的类:throttle_classes = [自己的访问频率控制类,]

  2. APIView 中dispatch方法封装了reqeust对象,initialize_request(request, *args, **kwargs)
    初始化方法: self.initial(request, *args, **kwargs) 初始化认证
     
    self.perform_authentication(request) #3.在这儿实现认证
     
    self.check_permissions(request) #4.权限检查
    &nbsp
    self.check_throttles(request) #5.访问频率控制
     
    def check_throttles(self, request):
    ...
    for throttle in self.get_throttles(): #循环认证我们自己的访问频率控制类
    ....if not throttle.allow_request(request, self): #调用里面的allow_request 方法
    ........self.throttled(request, throttle.wait()) #抛出异常

  3. SimpleThrottle中:cache = default_cache 调用系统提供的cache-api接口
    重写get_cache_key方法,返回自己将用来存储缓存的key