Джанго ручное управление доработкой - PullRequest
0 голосов
/ 13 октября 2019

У меня есть конечная точка, где я обычно кеширую данные. Но я хочу обновлять данные каждые несколько часов.

Поэтому я хочу реализовать условие, подобное:

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

Проблема в том, что API Django поддерживает только last_modifed(callback_that_gets_last_modified), что сравнивает обавремя последнего изменения и устанавливает его равным значению в ответе HTTP. Как я могу управлять этими двумя значениями по отдельности?

PS: Мне нужна причина в том, что я посылаю некоторую информацию, которая истекает через X секунд. Так что если X / 2 секунды уже прошло, я хочу обновить его

Ответы [ 2 ]

1 голос
/ 22 октября 2019

Если возможно, я бы порекомендовал хранить кэш на стороне сервера и использовать стандартный декоратор Django View @last_modified(last_modified_func), где last_modified_func - это функция, которую вы пишете, которая возвращает время самой последней версии с кэшированием на сервере (если в течение последнего часа) или datetime.datetime.now() (если он старше и его необходимо пересчитать). Это дает следующие преимущества:

  • Если к ресурсу обращаются несколько пользователей, его нужно рассчитывать только один раз в час, а не один раз в час на пользователя .
  • Если два пользователя одновременно обращаются к одному и тому же ресурсу, они получат один и тот же результат, а не один получит новый результат, в то время как другой получит 304_not_modified для более раннего результата.
  • Серверный кеш полностью находится под вашим контролем, независимо от того, какие пользователи используют разные настройки браузера и т. Д., Что может не соответствовать вашим пожеланиям по кешированию.

Однако, если вы полны решимости делать то, что выописано, это можно сделать. Это будет выглядеть скорее как стандартные функции Django в django.utils.cache , сокращенные для обработки только случая '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()) 

EDIT: Когда требуется пересчет, last_modified_func должен возвращать now (), а не None.

1 голос
/ 20 октября 2019

Вы можете обновить данные с желаемым поведением, не зная измененного, поскольку в запросе с 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),текущее время будет возвращено с округлением до часа. Пользователи, которые в последний раз модифицировали в текущий час, получат 304 без изменений, а пользователи из предыдущих часов получат обновленные данные.

...