为日历日期缓存Django查询集
我有一个查询,它的结果每天只会改变一次。每次有人请求这个页面时都去执行这个查询,感觉有点浪费。我正在考虑使用memcached来解决这个问题。
我该怎么开始呢?有没有人能给我一些建议或者在使用Django的缓存时需要避免的坑?我应该在模板里缓存还是在视图里缓存呢?
这个问题可能听起来有点模糊,但其实是因为我之前从来没有接触过缓存。如果有什么我可以进一步解释的,请随时问我。
进一步说明
根据Ken Cochrane的说法:
这个数据多久会变化一次:相关的数据会在那一天锁定。所以,比如说,我会提取2011年1月30日的数据,我可以接受在整个一天内都使用这个缓存的副本,直到2011年1月31日再刷新一次。
我在多个地方使用这个数据吗:只在一个视图里使用。
这个数据量有多大:大约有10个模型对象,每个对象有15个字段,最大的字段是一个
CharField(max_length=120)
。我会使用values()
把字段数量减少到大约一半。
3 个回答
你可以使用Python内置的 lru_cache
来根据日期缓存函数的结果,只要方法的参数是一个简单的“2021-09-22”格式的日期,而不是时间戳:
import datetime
from functools import lru_cache
@lru_cache(maxsize=1)
def my_func(date: datetime.date):
if type(date) is not datetime.date:
raise ValueError(f"This method is cached by calendar date, but received date {date}.")
首先,试着先了解这个内容。Django有一个功能,可以使用{% cache for_seconds something %}来缓存数据。只需要使用缓存标签就可以了。想了解更多,可以查看这个链接:http://docs.djangoproject.com/en/dev/topics/cache/
通常在决定在哪里进行缓存之前,我会问自己几个问题。
- 这些数据多久会变化一次?
- 我在多个地方使用这些数据吗?
- 数据量有多大?
因为我不知道你应用的所有细节,所以我会做一些假设。
- 你有一个视图,它要么接收一个日期,要么使用当前日期来查询数据库,提取该日期的所有日历事件。
- 你只在一个模板上显示这些信息。
- 数据量不大(少于100条记录)。
根据这些假设,你有三个选择: 1. 缓存模板 2. 缓存视图 3. 缓存查询集
通常我会选择缓存查询集,这样我可以更好地控制数据的缓存方式,并且可以在多个地方重复使用相同的缓存数据。
我发现缓存查询集最简单的方法是在相关模型的ModelManager中进行。我会创建一个像get_calender_by_date(date)这样的函数,来处理查询和缓存。以下是一个粗略的示例:
CACHE_TIMEOUT_SECONDS = 60 * 60 * 24 # this is 24 hours
class CalendarManager(models.Manager):
def get_calendar_by_date(self, by_date):
""" assuming date is a datetime object """
date_key = by_date.strftime("%m_%d_%Y")
cache_key = 'CAL_DATE_%s' % (date_key)
cal_date = cache.get(cache_key)
if cal_date is not None:
return cal_date
# not in cache get from database
cal_date = self.filter(event_date=by_date)
# set cal_date in cache for later use
cache.set(cache_key, cal_date, CACHE_TIMEOUT_SECONDS)
return cal_date
在缓存时需要注意的一些事项:
- 确保你存储在缓存中的对象可以被序列化。
- 由于memcache不知道今天是什么时候,你需要确保不要缓存过久。例如,如果是在1月21日中午缓存了24小时,那么这些日历信息会一直显示到1月22日中午,这可能不是你想要的。因此,设置查询的缓存时间时,要么设置一个较小的值让它更快过期,要么计算好缓存的时间,以便在你想要的时候过期。
- 确保你知道想要缓存的对象的大小。如果你的memcache实例只有16MB的存储空间,但你想存储32MB的数据,那么缓存对你来说就没什么用。
当缓存模板或视图时,你需要注意以下几点:
- 设置缓存超时时间不要太长,我认为你不能通过编程方式改变模板的缓存超时时间,而且它是硬编码的,所以如果设置得太高,你可能会得到过时的页面。你应该能够通过编程方式改变缓存时间,这样会更安全一些。
- 如果你在缓存模板,而模板上还有其他动态信息经常变化,确保只在你想要缓存一段时间的页面部分周围放置缓存标签。如果放错地方,可能会导致错误的结果。
希望这些信息能帮助你入门。祝你好运。