码迷,mamicode.com
首页 > 系统相关 > 详细

tastypie使用cache对list data无效问题

时间:2015-07-16 22:34:41      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:django   cache   tastypie   缓存   redis   

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

  

  环境: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 result
        set 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] = bundles
        to_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 result
        set 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 result
        set 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] = bundles
        to_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized)
        return self.create_response(request, to_be_serialized)

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

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

本文出自 “7673365” 博客,请务必保留此出处http://7683365.blog.51cto.com/7673365/1675359

tastypie使用cache对list data无效问题

标签:django   cache   tastypie   缓存   redis   

原文地址:http://7683365.blog.51cto.com/7673365/1675359

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!