【发布时间】:2015-04-10 20:54:55
【问题描述】:
我已经为此苦苦挣扎了好几个小时:我只是想不出一个合适的方法来缓存对象查询集结果 (object = queryset.get()) 以避免重新命中每个视图请求的数据库。
这是我当前的(简化的)代码,如您所见,我重写了 get_object() 以添加一些额外的数据(不仅是 today 变量),检查对象是否在会话中并将对象添加到会话。
views.py
from myapp import MyModel
from django.core.cache.utils import make_template_fragment_key
from django.views.generic import DetailView
class myClassView(DetailView):
model = MyModel
def get_object(self,queryset=None):
if queryset is None:
queryset = self.get_queryset()
pk = self.kwargs.get(self.pk_url_kwarg, None)
if pk is not None:
queryset = queryset.filter(pk=pk)
else:
raise AttributeError("My error message.")
try:
today = datetime.today().strftime('%Y%m%d')
cache_key = make_template_fragment_key('some_name', [pk, today])
if cache.has_key(cache_key):
object = self.request.session[cache_key]
return object
else:
object = queryset.get()
object.id = my_id
object.today = today
# Add object to session
self.request.session[cache_key] = object
except queryset.model.DoesNotExist:
raise Http404("Error 404")
return object
只有当我添加以下内容时,上述内容才有效:
settings.py
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
但我不喜欢这种 hack,因为它对 Django 1.6 和更新版本不安全,因为根据 How To Use Sessions (Django 1.7 documents):
如果 SECRET_KEY 没有保密并且您正在使用 PickleSerializer,这可能会导致任意远程代码执行
如果我不添加 SESSIONS_SERIALIZER 行,我会收到“django object is not JSON serializable”错误。但是,在其他地方我的代码中断,并且在尝试从会话中提取数据时出现 KeyError 错误。将我的字符串键转换为整数解决了这个问题。在更改设置文件之前,Django 在请求会话数据时自动将 str 键转换为整数。
所以考虑到这个会话序列化程序安全问题,我更喜欢其他选项。所以我阅读了here 和here 关于缓存get_object() 的内容,但我只是不知道如何将其放入我的get_object() 位。我试过了。。
if cache.has_key(cache_key):
self._object = super(myClassView,self).get_object(queryset=None)
return self._object
...但它失败了。这似乎是迄今为止最好的解决方案。但是如何在我的代码中实现它呢?或者,有更好的主意吗?我全是耳朵。谢谢!
【问题讨论】:
标签: session caching django-class-based-views django-1.7