Django手动控制modified-since

Django manual control of modified-since

我有一个端点,我通常在其中缓存数据。但是我想每隔几个小时刷新一次数据。

所以我想实现类似于以下的条件:

if  now() - header.last_modified > one_hour:
    return create_new_data_with_last_modified_set_to_now()
else:
    return http_answer_304_not_modified()

问题是 Django 的 API 只支持 last_modifed(callback_that_gets_last_modified) 两者都比较最后修改时间,并在 HTTP 响应上将其设置为相同的值。 如何分别控制这两个值?

P.S:我需要这个的原因是我发送了一些在 X 秒后超时的信息。所以如果 X/2 秒已经过去了,我想刷新它

您可以使用所需的行为刷新数据,而无需使用 callback_that_gets_last_modified 请求修改后的数据,如下所示:

def get_cache_last_modified():
    return datetime.datetime.utcfromtimestamp((datetime.datetime.now() - datetime.datetime.utcfromtimestamp(0)).total_seconds() // (X/2) * (X/2))

例如,如果您的数据每两小时更新一次 (X==7200),它会将当前时间 return 向下舍入为一小时。当前小时最后修改的用户将获得 304 未修改,之前小时的用户将获得刷新数据。

如果可能,我建议在服务器端保留缓存,并使用标准的 Django 视图装饰器 @last_modified(last_modified_func),其中 last_modified_func 是您编写的函数,其中 returns最近的服务器缓存版本的时间(如果在过去一小时内)或 datetime.datetime.now()(如果它更旧并且需要重新计算)。这样做有以下优点:

  • 如果多个用户正在访问该资源,则只需每小时计算一次,而不是每小时计算一次每个用户
  • 如果两个用户同时访问同一个资源,他们将得到相同的结果,而不是一个得到新的结果,而另一个仍然304_not_modified得到一个较早的结果。
  • 服务器端缓存完全在您的控制之下,无论用户使用不同的浏览器设置等,这可能不符合您的缓存意愿。

但是,如果您下定决心按照您描述的去做,那是可以做到的。它看起来很像 django.utils.cache 中的标准 Django 函数,简化为仅处理大小写 'if_modified_since'。在你的 Django 视图中是这样的:

import datetime
from django.utils.http import http_date, parse_http_date_safe
from django.http import HttpResponseNotModified

if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
if_modified_since = if_modified_since and parse_http_date_safe(if_modified_since)
one_hour_ago = datetime.datetime.now() - datetime.timedelta(hours=1)
if if_modified_since and if_modified_since > one_hour_ago:
    return HttpResponseNotModified()
# otherwise create and return new response here...
# then before sending it, set Last-Modified header:
response['Last-Modified'] = http_date(datetime.datetime.now()) 

编辑:当需要重新计算时,last_modified_func 应该 return now(),而不是 None。