这就算是第一篇博客了,我老大陈如杰(一个牛逼的程序员)讲过,只有自己研究了的东西才能写到博客上,我谨遵教诲。

环境:Django==1.8.2、django-tastypie==0.12.2-dev、redis==2.10.3、django-redis==4.1.0

django配置了使用redis作为后台缓存

在ubuntu中安装了redis-server(sudo apt-get install redis-server),在django的settings中加入如下配置:(具体可以参考http://niwinz.github.io/django-redis/latest/)

# to set django's default cache add by minkedong
CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379/1","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}}
}

在写tastypie自己的ModelResource时,在Meta中加入:

cache = SimpleCache(timeout=8*60*60)

当我请求此ModelResource的时候,发出GET请求“/api/v1/author/1/”后,在ubuntu的bash中使用命令:redis-cli -n 1 进入redis,在redis中键入命令:keys *,查看到已经缓存了此API的请求结果。

但当我发出GET请求"/api/v1/author/"后,进入redis查看,发现并没有缓存我的结果。

果断进入tastypie的源码查看,在"tastypie.resources.ModelResource"中有如下两个方法:

    def get_list(self, request, **kwargs):"""Returns a serialized list of resources.Calls ``obj_get_list`` to provide the data, then handles that resultset and serializes it.Should return a HttpResponse (200 OK)."""# TODO: Uncached for now. Invalidation that works for everyone may be#       impossible.base_bundle = self.build_bundle(request=request)objects = self.obj_get_list(bundle=base_bundle, **self.remove_api_resource_names(kwargs))sorted_objects = self.apply_sorting(objects, options=request.GET)paginator = self._meta.paginator_class(request.GET, sorted_objects, resource_uri=self.get_resource_uri(), limit=self._meta.limit, max_limit=self._meta.max_limit, collection_name=self._meta.collection_name)to_be_serialized = paginator.page()# Dehydrate the bundles in preparation for serialization.bundles = []for obj in to_be_serialized[self._meta.collection_name]:bundle = self.build_bundle(obj=obj, request=request)bundles.append(self.full_dehydrate(bundle, for_list=True))to_be_serialized[self._meta.collection_name] = bundlesto_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized)return self.create_response(request, to_be_serialized)def get_detail(self, request, **kwargs):"""Returns a single serialized resource.Calls ``cached_obj_get/obj_get`` to provide the data, then handles that resultset and serializes it.Should return a HttpResponse (200 OK)."""basic_bundle = self.build_bundle(request=request)try:obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs))except ObjectDoesNotExist:return http.HttpNotFound()except MultipleObjectsReturned:return http.HttpMultipleChoices("More than one resource is found at this URI.")bundle = self.build_bundle(obj=obj, request=request)bundle = self.full_dehydrate(bundle)bundle = self.alter_detail_data_to_serialize(request, bundle)return self.create_response(request, bundle)

使用pdb打断点,发现“/api/v1/author/1/”请求调用get_detail方法,而"/api/v1/author/"请求调用get_list方法,从源码中不难看出,get_detail中调用了cached_obj_get方法,其从cache中拿数据,而get_list调用了obj_get_list方法(源码中有cached_obj_get_list方法,其并未调用),即未从cache中拿数据(其实get_list方法的注释中已经给出了解释

# TODO: Uncached for now. Invalidation that works for everyone may be impossible.),好吧,那解决方式就比较简单了,直接在自己的ModelResource中覆盖掉此方法,更改成:

   def get_list(self, request, **kwargs):"""Returns a serialized list of resources.Calls ``obj_get_list`` to provide the data, then handles that resultset and serializes it.Should return a HttpResponse (200 OK)."""# TODO: Uncached for now. Invalidation that works for everyone may be#       impossible.base_bundle = self.build_bundle(request=request)objects = self.cached_obj_get_list(bundle=base_bundle, **self.remove_api_resource_names(kwargs))sorted_objects = self.apply_sorting(objects, options=request.GET)paginator = self._meta.paginator_class(request.GET, sorted_objects, resource_uri=self.get_resource_uri(), limit=self._meta.limit, max_limit=self._meta.max_limit, collection_name=self._meta.collection_name)to_be_serialized = paginator.page()# Dehydrate the bundles in preparation for serialization.bundles = []for obj in to_be_serialized[self._meta.collection_name]:bundle = self.build_bundle(obj=obj, request=request)bundles.append(self.full_dehydrate(bundle, for_list=True))to_be_serialized[self._meta.collection_name] = bundlesto_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized)return self.create_response(request, to_be_serialized)

再次请求"/api/v1/author/"后,发现redis中已经缓存了此结果!

但是,这里面后面的实际请求会有一个问题,那就是当你请求“/api/v1/author/”和请求“/api/v1/author/?format=json&name=jack”(假设有name筛选参数),其返回的json数据都是全量的数据,为什么呢?因为他在redis中生成的cache key都是一样的,我们要针对不同的请求参数生成不同的cache key,相当于不同的请求参数也cache一份数据。我的做法如下,直接在自己的ModelResource中覆盖掉cached_obj_get_list方法,更改成:

def cached_obj_get_list(self, bundle, **kwargs):"""更改get_list的cache key,使其对不同参数存不同的cache key"""if hasattr(bundle.request, 'GET'):# Grab a mutable copy.filters = bundle.request.GET.copy()filters.update(kwargs)applicable_filters = self.build_filters(filters=filters)applicable_str = ':'.join(sorted(["%s=%s" % (key, ','.join(value) if type(value) == type([]) else value, ) for key, value in applicable_filters.items()]))cache_key = self.generate_cache_key('list', applicable_str, **kwargs)obj_list = self._meta.cache.get(cache_key)if obj_list is None:obj_list = self.obj_get_list(bundle=bundle, **kwargs)self._meta.cache.set(cache_key, obj_list)return obj_list

因为对redis的机制不太了解,后面自己将研究一下redis的东西,有什么错误,欢迎大家指正!

转载于:https://blog.51cto.com/7683365/1675359

tastypie使用cache对list data无效问题相关推荐

  1. vue更新data无效,页面data没刷新 vue.set

    Vue中组件的data是有很多坑的,先普及一下常识: 1.想使用data,必须先在data中创建.(如果不创建就会报错)示例: <div class="">{{user ...

  2. [mmu/cache]-ARM cache的学习笔记-一篇就够了

    ★★★ 个人博客导读首页-点击此处 ★★★ . 说明: 在默认情况下,本文讲述的都是ARMV8-aarch64架构,linux kernel 64位 . 相关文章 1.ARM MMU的学习笔记-一篇就 ...

  3. 从Java视角理解CPU缓存(CPU Cache)

    http://coderplay.iteye.com/blog/1485760 众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存 ...

  4. Linux内存之Cache

    一. Linux内存之Cache 1.1.Cache 1.1.1.什么是Cache? Cache存储器,是位于CPU和主存储器DRAM之间的一块高速缓冲存储器,规模较小,但是速度很快,通常由SRAM( ...

  5. Linux内存管理:ARM64体系结构与编程之cache(3):cache一致性协议(MESI、MOESI)、cache伪共享

    目录 为什么系统软件人员要深入了解cache? cache一致性协议 神马是MESI协议? MESI的操作 MESI状态图 演示:初始化状态为I的cache line 当本地CPU的缓存行状态为I时, ...

  6. 缓存与缓冲的区别 Difference Between Cache and Buffer

    2019独角兽企业重金招聘Python工程师标准>>> Cache vs Buffer Both cache and buffer are temporary storage are ...

  7. cache stm32h7_【STM32H7教程】第24章 STM32H7的Cache解读(非常重要)

    _CleanDCache和SCB_InvalidateDCache是对整个Cache的操作,所以比最后的三个函数SCB_InvalidateDCache_by_Addr,SCB_CleanDCache ...

  8. 【ZYNQ】 cache解决问题

    在进行PS-PL之间的DMA传输时,不可避免会遇到Cache问题.今天在这里讲一下Cache的解决方法.其中参考了forums.xilinx.com的处理方法. 首先解释为什么DMA会引入Cache问 ...

  9. 【STM32H7教程】第24章 STM32H7的Cache解读(非常重要)

    完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第24章       STM32H7的Cache解读(非常重要 ...

最新文章

  1. Apache软件基金会宣布Apache Unom成为顶级项目
  2. 深度解析dba_segments和sys.seg$中的细节差异(下)
  3. 和Facebook竞争,社交平台Mico怎样在1年内获得3000万用户?
  4. Java黑皮书课后题第6章:*6.16(一年的天数)使用下面的方法体编写一个方法,返回一年的天数。编写一个测试程序,显示从2000年到2020年间每年的天数
  5. flask中 app.run(host='0.0.0.0', port=5000, debug=False) 不能用外网ip访问的解决办法
  6. linux nfs命令,linux命令:NFS服务
  7. 编写高质量代码的50条黄金守则
  8. linux挂载华为存储fc,linux 挂载存储设备
  9. C++算法学习(力扣:1254. 统计封闭岛屿的数目)
  10. 利用工具,促进有效沟通
  11. html合并单元格_HTML基础2
  12. 西门子PLCSIM仿真与第三方组态软件(包括HMI)的通信
  13. 微星主板Ubuntu16.04安装教程
  14. 网吧计费管理系统(武汉理工大学大一下实验(C语言版源码))
  15. DNA损伤修复基因数据库
  16. [HLSL]HLSL 入门参考 (dx11龙书附录B译文)
  17. iOS视频播放的基本方法
  18. 服务器磁带断带修复,易备磁带版:安全合规、功能超群–Windows服务器的磁带备份软件...
  19. 【小程序】开发需要注意的地方(三)
  20. 《Microsoft COCO Captions Data Collection and Evaluation Server》论文笔记

热门文章

  1. 云计算的SPI服务模型
  2. ES6新特性_ES6语法糖-class中的getter和setter设置---JavaScript_ECMAScript_ES6-ES11新特性工作笔记038
  3. Vue条件渲染---vue工作笔记0008
  4. OAuth2.0_环境搭建_Spring Security OAuth2.0认证授权---springcloud工作笔记139
  5. STM32工作笔记0067---SPI接口原理与配置
  6. C#.Net工作笔记016---C#中使用反射对两个对象copy复制内容
  7. plsql数据库异常---plsql 登录后,提示数据库字符集(AL32UTF8)和客户端字符集(ZHS16GBK)不一致
  8. no module named google.protobuf.internal
  9. fastadmin添加定时任务
  10. android wear 同步应用,Android Wear发布 突出语音及同步功能