Django REST Framework
  • Overview
    • Django REST framework
    • Быстрый старт
      • Сериализация
      • Запросы-ответы
      • Представления-классы
      • Аутентификация/права доступа
      • Отношения и связи
      • Наборы представлений и роутеры
    • Навигация по API:
      • Запросы
      • Ответы
      • Представления
      • Общие представления
      • Viewsets
      • Маршрутизаторы
      • Парсеры
      • Рендереры
      • Сериализаторы
      • Поля сериализатора
      • Отношения сериализаторов
      • Валидаторы
      • Аутентификация
      • Разрешения
      • Кэширование
      • Дросселирование
      • Фильтрация
      • Пагинация
      • Версионирование
      • Согласование контента
      • Метаданные
      • Schemas
      • Cуффиксы формата
      • Возвращение URL-адресов
      • Исключения
      • Коды состояния
      • Тестирование
      • Настройки
  • Статьи
    • Статьи
      • AJAX, CSRF & CORS
      • The Browsable API
      • Улучшения в браузере
      • Документирование вашего API
      • HTML и формы
      • Интернационализация
      • REST, гипермедиа и HATEOAS
      • Вложенные сериализаторы с возможностью записи
Powered by GitBook
On this page
  • Согласование контента
  • Определение выбранного рендерера
  • Переговоры по пользовательскому контенту
  • Пример
  • Указание согласования контента

Was this helpful?

  1. Overview
  2. Навигация по API:

Согласование контента

PreviousВерсионированиеNextМетаданные

Last updated 2 years ago

Was this helpful?

Согласование контента

HTTP предусматривает несколько механизмов "согласования контента" - процесса выбора наилучшего представления для данного ответа при наличии нескольких представлений.

  • , Fielding et al.

Согласование контента - это процесс выбора одного из нескольких возможных форматов ответа для возврата клиенту, основанный на предпочтениях клиента или сервера.

Определение выбранного рендерера

DRF использует простой стиль согласования контента для определения того, какой формат данных должен быть возвращен клиенту, основываясь на доступных рендерерах, приоритетах каждого из них и заголовке клиента Accept:. Используемый стиль частично зависит от клиента, а частично от сервера.

  1. Более конкретным типам носителей отдается предпочтение перед менее конкретными типами носителей.

  2. Если несколько типов медиа имеют одинаковую специфичность, то предпочтение отдается на основе порядка рендеринга, настроенного для данного представления.

Например, при следующем заголовке Accept:

application/json; indent=4, application/json, application/yaml, text/html, */*

Приоритеты для каждого из указанных типов носителей будут следующими:

  • 'application/json; indent=4'

  • 'application/json', 'application/yaml' и 'text/html'

  • */*

Если запрашиваемое представление было настроено только с рендерерами для YAML и HTML, то DRF будет выбирать тот рендерер, который указан первым в списке renderer_classes или настройке DEFAULT_RENDERER_CLASSES.

Более подробную информацию о заголовке HTTP Accept смотрите в .


Примечание: Значения "q" не учитываются DRF при определении предпочтений. Использование значений "q" негативно влияет на кэширование, и, по мнению автора, это ненужный и слишком сложный подход к согласованию контента.

Это верный подход, поскольку спецификация HTTP намеренно не определяет, как сервер должен взвешивать предпочтения, основанные на сервере, против предпочтений, основанных на клиенте.


Переговоры по пользовательскому контенту

Маловероятно, что вы захотите предоставить пользовательскую схему согласования контента для DRF, но вы можете сделать это при необходимости. Для реализации пользовательской схемы согласования контента переопределите BaseContentNegotiation.

Классы согласования контента DRF обрабатывают выбор как подходящего парсера для запроса, так и подходящего рендерера для ответа, поэтому вы должны реализовать оба метода .select_parser(request, parsers) и .select_renderer(request, renderers, format_suffix).

Метод select_parser() должен вернуть один экземпляр парсера из списка доступных парсеров, или None, если ни один из парсеров не может обработать входящий запрос.

Метод select_renderer() должен возвращать кортеж из (экземпляр рендерера, тип медиа), либо вызывать исключение NotAcceptable.

Пример

Ниже представлен пользовательский класс согласования контента, который игнорирует запрос клиента при выборе подходящего парсера или рендерера.

from rest_framework.negotiation import BaseContentNegotiation

class IgnoreClientContentNegotiation(BaseContentNegotiation):
    def select_parser(self, request, parsers):
        """
        Select the first parser in the `.parser_classes` list.
        """
        return parsers[0]

    def select_renderer(self, request, renderers, format_suffix):
        """
        Select the first renderer in the `.renderer_classes` list.
        """
        return (renderers[0], renderers[0].media_type)

Указание согласования контента

Класс согласования контента по умолчанию можно установить глобально, используя настройку DEFAULT_CONTENT_NEGOTIATION_CLASS. Например, следующие настройки будут использовать наш пример класса IgnoreClientContentNegotiation.

REST_FRAMEWORK = {
    'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'myapp.negotiation.IgnoreClientContentNegotiation',
}

Вы также можете указать согласование контента, используемое для отдельного представления или набора представлений, используя представления на основе класса APIView.

from myapp.negotiation import IgnoreClientContentNegotiation
from rest_framework.response import Response
from rest_framework.views import APIView

class NoNegotiationView(APIView):
    """
    An example view that does not perform content negotiation.
    """
    content_negotiation_class = IgnoreClientContentNegotiation

    def get(self, request, format=None):
        return Response({
            'accepted media type': request.accepted_renderer.media_type
        })
RFC 2616
RFC 2616