Декоратор condition

Декоратор condition применяется к функциям представления и позволяет управлять кэшированием на основе условий ETag и Last-Modified. Он принимает два параметра: etag_func и last_modified_func, которые должны возвращать строку ETag и дату последнего изменения соответственно. Декоратор сравнивает заголовки запроса с вычисленными значениями и при совпадении возвращает ответ 304 Not Modified, что экономит трафик и ускоряет загрузку.

Синтаксис

pythonfrom django.views.decorators.http import condition

@condition(etag_func=None, last_modified_func=None)
def view_func(request):
  # логика представления
  return response

Пример

Давайте реализуем представление для отображения статьи с использованием декоратора condition для управления кэшированием:

pythonfrom django.views.decorators.http import condition
from django.http import HttpResponse
from myapp.models import Article
from datetime import datetime
import hashlib

def get_etag(request, article_id):
  article = Article.objects.get(id=article_id)
  content = f"{article.title}{article.updated_at}"
  return hashlib.md5(content.encode()).hexdigest()

def get_last_modified(request, article_id):
  article = Article.objects.get(id=article_id)
  return article.updated_at

@condition(etag_func=get_etag, last_modified_func=get_last_modified)
def article_detail(request, article_id):
  article = Article.objects.get(id=article_id)
  return HttpResponse(f"Article: {article.title}")

При повторном запросе той же статьи сервер вернёт ответ 304 Not Modified, если статья не изменилась:

python"Response status: 304 Not Modified"

Пример

Рассмотрим пример использования декоратора condition с одной функцией вычисления ETag:

pythonfrom django.views.decorators.http import condition
from django.http import JsonResponse
from myapp.models import Article
import hashlib

def article_etag(request, article_id):
  article = Article.objects.get(id=article_id)
  content = f"{article.title}{article.content}"
  return hashlib.sha256(content.encode()).hexdigest()

@condition(etag_func=article_etag)
def article_json(request, article_id):
  article = Article.objects.get(id=article_id)
  data = {"title": article.title, "content": article.content}
  return JsonResponse(data)

Если ETag совпадает с заголовком If-None-Match запроса, Django автоматически вернёт ответ 304 Not Modified:

python"Response: 304 Not Modified (cached)"

Пример

Использование декоратора condition только с функцией вычисления даты последнего изменения:

pythonfrom django.views.decorators.http import condition
from django.http import HttpResponse
from myapp.models import Article
from datetime import datetime

def get_last_modified(request, article_id):
  article = Article.objects.get(id=article_id)
  return article.updated_at

@condition(last_modified_func=get_last_modified)
def article_view(request, article_id):
  article = Article.objects.get(id=article_id)
  return HttpResponse(f"<h1>{article.title}</h1><p>{article.content}</p>")

При запросе с заголовком If-Modified-Since сервер возвращает 304 Not Modified, если статья не обновлялась:

python"HTTP/1.1 304 Not Modified"

Пример

Комбинированное использование condition с обеими функциями для максимальной эффективности кэширования:

pythonfrom django.views.decorators.http import condition
from django.http import HttpResponse
from myapp.models import Article
from datetime import datetime
import hashlib

def get_etag(request, article_id):
  article = Article.objects.get(id=article_id)
  return hashlib.md5(article.content.encode()).hexdigest()

def get_last_modified(request, article_id):
  article = Article.objects.get(id=article_id)
  return article.updated_at

@condition(etag_func=get_etag, last_modified_func=get_last_modified)
def article_secure(request, article_id):
  article = Article.objects.get(id=article_id)
  return HttpResponse(f"Article secure: {article.title}")

При выполнении запроса сервер проверит оба условия и при совпадении вернёт 304 Not Modified:

python"Status: 304 Not Modified (both ETag and Last-Modified match)"

Смотрите также

  • декоратор etag,
    который управляет кэшированием только через ETag
  • декоратор last_modified,
    который управляет кэшированием только через дату изменения
  • класс HttpResponseNotModified,
    который возвращает ответ 304 без содержимого
  • декоратор gzip_page,
    который сжимает ответ для экономии трафика