【问题标题】:Caching a Django queryset for the calendar date为日历日期缓存 Django 查询集
【发布时间】:2011-06-16 14:14:33
【问题描述】:

我有一个查询,结果每天只更改一次。我为该页面收到的每个请求都执行该查询似乎是一种浪费。我正在研究为此使用 memcached。

我将如何开始?在使用 Django 的缓存时,有人有什么建议或陷阱吗?我应该缓存在模板还是视图?

这个问题可能看起来很模糊,但这只是因为我以前从未处理过缓存。所以如果有什么我可以详细说明的,问。

细化

根据 Ken Cochrane:

  1. 此数据多久更改一次:相关数据将在该日历日期锁定。因此,例如,我将提取 2011 年 1 月 30 日的数据,我可以在 2011 年 1 月 31 日之前全天提供该缓存副本,然后刷新。

  2. 我是否在多个地方使用此数据:仅在一个视图中。

  3. 将有多少数据:平均 10 个模型对象包含大约 15 个字段,其中最大的是 CharField(max_length=120)。我将使用values() 将字段数量减少到大约一半。

【问题讨论】:

    标签: python django memcached django-queryset django-cache


    【解决方案1】:

    您可以使用 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}.")
    

    【讨论】:

      【解决方案2】:

      通常在决定在哪里进行缓存之前,我会问自己几个问题。

      1. 此数据多久更改一次
      2. 我是否在不止一个地方使用此数据
      3. 会有多少数据

      由于我不知道您的应用程序的所有细节,我将做一些假设。

      1. 您有一个视图,该视图要么接收日期,要么使用当前日期来查询数据库以提取该日期的所有日历事件。
      2. 您只在一个模板上显示此信息,
      3. 数据量不太大(少于 100 个条目)。

      根据这些假设,您有 3 个选项。 1.缓存模板 2.缓存视图 3. 缓存查询集

      通常,当我进行缓存时,我会缓存查询集,这使我可以更好地控制我想要缓存数据的方式,并且我可以在多个地方重复使用相同的缓存数据。

      我发现缓存查询集的最简单方法是在 ModelManger 中为相关模型执行此操作。我会创建一个像 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
      

      缓存时需要注意的一些事项

      1. 确保您存储在缓存中的对象可以腌制
      2. 由于 memcache 不知道现在是哪一天,因此您需要确保不会过度缓存。例如,如果它是 1 月 21 日中午并且您缓存了 24 小时,则该日历信息将显示到 1 月 22 日中午,这可能不是您要查找的内容,因此请确保在设置查询时间时要么将其设置为一个较小的值,以使其更快过期,要么您计算缓存多长时间,以便在您希望它过期时过期。
      3. 确保您知道要缓存的对象的大小。如果您的 memcache 实例只有 16MB 的存储空间,但您想存储 32MB 的数据,那么缓存对您没有多大用处。

      缓存模板或视图时需要注意以下事项

      1. 设置您的缓存超时,使其不会太大,我认为您不能以编程方式更改模板缓存超时,并且它是硬编码的,因此如果您将其设置得太高,您最终会得到一个页面那已经过时了。您应该能够以编程方式更改缓存时间,这样会更安全一些。
      2. 如果您正在缓存模板并且模板上的其他信息是动态的并且一直在变化,请确保您只将缓存标记放在您想要缓存一段时间的页面部分周围。如果你把它放在错误的地方,你可能会得到错误的结果。

      希望这可以为您提供足够的入门信息。祝你好运。

      【讨论】:

      • +1 以获得广泛的答案。就您的假设而言:您是正确的:“您的观点要么接受日期,要么使用当前日期”。那是正确的。我使用当前日期来提取项目。在其他 2 个假设上,你是有钱的。再次感谢!我会等待其他建议,但感谢您的及时回复。
      【解决方案3】:

      首先尝试阅读此内容。 Django 有能力 {% cache for_seconds something %} 只需使用缓存标签。 http://docs.djangoproject.com/en/dev/topics/cache/

      【讨论】:

      • 如何设置日历日期?
      猜你喜欢
      • 1970-01-01
      • 2011-03-30
      • 2015-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多