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。
我有一个端点,我通常在其中缓存数据。但是我想每隔几个小时刷新一次数据。
所以我想实现类似于以下的条件:
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。