Рендереры¶
Прежде чем экземпляр TemplateResponse будет возвращен клиенту, он должен быть отрисован. Процесс рендеринга принимает промежуточное представление шаблона и контекста и превращает его в конечный поток байтов, который может быть передан клиенту.
‒ Django documentation
REST framework включает в себя несколько встроенных классов Renderer, которые позволяют возвращать ответы с различными типами медиа. Также имеется поддержка определения собственных пользовательских рендереров, что дает вам гибкость в разработке собственных типов медиа.
Как определяется рендерер¶
Набор допустимых рендереров для представления всегда определяется как список классов. При входе в представление фреймворк REST будет выполнять согласование содержимого входящего запроса и определять наиболее подходящий рендерер для удовлетворения запроса.
Основной процесс согласования содержимого включает изучение заголовка Accept запроса, чтобы определить, какие типы медиа ожидаются в ответе.  По желанию, суффиксы формата в URL могут быть использованы для явного запроса определенного представления.  Например, URL http://example.com/api/users_count.json может быть конечной точкой, которая всегда возвращает данные в формате JSON.
Для получения дополнительной информации см. документацию по content negotiation.
Настройка рендеринга¶
Набор рендереров по умолчанию может быть установлен глобально, с помощью параметра DEFAULT_RENDERER_CLASSES.  Например, следующие настройки будут использовать JSON в качестве основного типа медиа, а также включать API самоописания.
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ]
}
Вы также можете установить рендереры, используемые для отдельного представления или набора представлений, используя APIView представления на основе класса.
from django.contrib.auth.models import User
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
class UserCountView(APIView):
    """
    A view that returns the count of active users in JSON.
    """
    renderer_classes = [JSONRenderer]
    def get(self, request, format=None):
        user_count = User.objects.filter(active=True).count()
        content = {'user_count': user_count}
        return Response(content)
Или, если вы используете декоратор @api_view с представлениями, основанными на функциях.
@api_view(['GET'])
@renderer_classes([JSONRenderer])
def user_count_view(request, format=None):
    """
    A view that returns the count of active users in JSON.
    """
    user_count = User.objects.filter(active=True).count()
    content = {'user_count': user_count}
    return Response(content)
Упорядочивание классов рендеринга¶
Важно при определении классов рендереров для вашего API подумать о том, какой приоритет вы хотите присвоить каждому типу медиа.  Если клиент недоопределит представления, которые он может принять, например, отправит заголовок Accept: */* или вообще не включит заголовок Accept, то REST framework выберет первый рендерер в списке для использования в ответе.
Например, если ваш API обслуживает JSON-ответы и HTML-просмотр, вы можете захотеть сделать JSONRenderer вашим рендерером по умолчанию, чтобы отправлять JSON ответы клиентам, которые не указывают заголовок Accept.
Если ваш API включает представления, которые могут обслуживать как обычные веб-страницы, так и ответы API в зависимости от запроса, то вы можете сделать TemplateHTMLRenderer рендерером по умолчанию, чтобы хорошо играть со старыми браузерами, которые посылают broken accept headers.
Справочник по API¶
JSONRenderer¶
Переводит данные запроса в JSON , используя кодировку utf-8.
Обратите внимание, что стиль по умолчанию включает символы юникода и отображает ответ, используя компактный стиль без лишних пробелов:
{"unicode black star":"★","value":999}
Клиент может дополнительно включить параметр типа медиа 'indent', в этом случае возвращаемое JSON будет с отступом.  Например, Accept: application/json; indent=4.
{
    "unicode black star": "★",
    "value": 999
}
Стиль кодировки JSON по умолчанию может быть изменен с помощью клавиш настройки UNICODE_JSON и COMPACT_JSON.
.media_type : application/json
.format : 'json'
.charset : None
TemplateHTMLRenderer¶
Рендерит данные в HTML, используя стандартный шаблонный рендеринг Django. В отличие от других рендереров, данные, передаваемые в Response, не нужно сериализовать.  Также, в отличие от других рендереров, вы можете захотеть включить аргумент template_name при создании Response.
TemplateHTMLRenderer создаст RequestContext , используя response.data в качестве диктанта контекста, и определит имя шаблона, который будет использоваться для рендеринга контекста.
Примечание: При использовании с представлением, которое использует сериализатор, Response, отправленный для рендеринга, может не быть словарем и должен быть обернут в dict перед возвратом, чтобы TemplateHTMLRenderer смог его отрендерить. Например:
response.data = {'results': response.data}
Имя шаблона определяется (в порядке предпочтения):
Явный аргумент
template_name, передаваемый в ответ.Явный набор атрибутов
.template_nameдля этого класса.Возвращаемый результат вызова
view.get_template_names().
Пример представления, которое использует TemplateHTMLRenderer :
class UserDetail(generics.RetrieveAPIView):
    """
    A view that returns a templated HTML representation of a given user.
    """
    queryset = User.objects.all()
    renderer_classes = [TemplateHTMLRenderer]
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return Response({'user': self.object}, template_name='user_detail.html')
Вы можете использовать TemplateHTMLRenderer либо для возврата обычных HTML-страниц с помощью фреймворка REST, либо для возврата HTML- и API-ответов с одной конечной точки.
Если вы создаете сайты, использующие TemplateHTMLRenderer наряду с другими классами рендеринга, вам следует рассмотреть возможность включения TemplateHTMLRenderer в качестве первого класса в списке renderer_classes, чтобы он был приоритетным даже для браузеров, посылающих плохо сформированные заголовки ACCEPT:.
Дополнительные примеры использования ** *HTML & Forms* Topic Page см. в TemplateHTMLRenderer.
.media_type : text/html
.format : 'html'
.charset : utf-8
См. также: StaticHTMLRenderer
StaticHTMLRenderer¶
Простой рендерер, который просто возвращает предварительно отрендеренный HTML. В отличие от других рендереров, данные, передаваемые в объект response, должны быть строкой, представляющей возвращаемое содержимое.
Пример представления, которое использует StaticHTMLRenderer :
@api_view(['GET'])
@renderer_classes([StaticHTMLRenderer])
def simple_html_view(request):
    data = '<html><body><h1>Hello, world</h1></body></html>'
    return Response(data)
Вы можете использовать StaticHTMLRenderer либо для возврата обычных HTML-страниц с помощью фреймворка REST, либо для возврата HTML- и API-ответов с одной конечной точки.
.media_type : text/html
.format : 'html'
.charset : utf-8
См. также: TemplateHTMLRenderer
BrowsableAPIRenderer¶
Рендерит данные в HTML для Browsable API:
Этот рендерер определяет, какой другой рендерер имел бы наивысший приоритет, и использует его для отображения ответа в стиле API на HTML-странице.
.media_type : text/html
.format : 'api'
.charset : utf-8
.template : 'rest_framework/api.html'
Настройка BrowsableAPIRenderer¶
По умолчанию содержимое ответа будет отрисовываться рендерером с наивысшим приоритетом, кроме BrowsableAPIRenderer.  Если вам нужно настроить это поведение, например, использовать HTML в качестве формата возврата по умолчанию, но использовать JSON в просматриваемом API, вы можете сделать это, переопределив метод get_default_renderer().  Например:
class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
    def get_default_renderer(self, view):
        return JSONRenderer()
AdminRenderer¶
Рендерит данные в HTML для отображения в стиле администратора:
Этот рендерер подходит для веб-интерфейсов в стиле CRUD, которые также должны представлять удобный интерфейс для управления данными.
Обратите внимание, что представления, которые имеют вложенные или списковые сериализаторы для ввода, не будут хорошо работать с AdminRenderer , так как HTML формы не могут правильно их поддерживать.
Примечание : AdminRenderer может включать ссылки на детальные страницы только тогда, когда в данных присутствует правильно настроенный атрибут URL_FIELD_NAME (** url по умолчанию). Для HyperlinkedModelSerializer так и будет, но для ModelSerializer или простых Serializer классов вам нужно будет убедиться, что поле включено явно. Например, здесь мы используем метод models get_absolute_url:
class AccountSerializer(serializers.ModelSerializer):
    url = serializers.CharField(source='get_absolute_url', read_only=True)
    class Meta:
        model = Account
.media_type : text/html
.format : 'admin'
.charset : utf-8
.template : 'rest_framework/admin.html'
HTMLFormRenderer¶
Рендерит данные, возвращаемые сериализатором, в HTML-форму. Вывод этого рендерера не включает заключающие теги <form>, скрытый CSRF-вход или какие-либо кнопки отправки.
Этот рендерер не предназначен для прямого использования, но может быть использован в шаблонах путем передачи экземпляра сериализатора в тег шаблона render_form.
{% load rest_framework %}
<form action="/submit-report/" method="post">
    {% csrf_token %}
    {% render_form serializer %}
    <input type="submit" value="Save" />
</form>
Для получения дополнительной информации см. документацию HTML & Forms.
.media_type : text/html
.format : 'form'
.charset : utf-8
.template : 'rest_framework/horizontal/form.html'
MultiPartRenderer¶
Этот рендерер используется для рендеринга данных многочастной формы HTML. Он не подходит в качестве рендеринга ответов , а используется для создания тестовых запросов, используя test client and test request factory фреймворка REST.
.media_type : multipart/form-data; boundary=BoUnDaRyStRiNg
.format : 'multipart'
.charset : utf-8
Пользовательские рендереры¶
Для реализации пользовательского рендерера необходимо переопределить BaseRenderer , установить свойства .media_type и .format и реализовать метод .render(self, data, media_type=None, renderer_context=None).
Метод должен возвращать байтстринг, который будет использоваться в качестве тела ответа HTTP.
Аргументы, передаваемые методу .render(), следующие:
Данные запроса, заданные инстанцией Response().
Необязательно. Если указано, то это принятый тип носителя, определенный на этапе согласования содержимого.
В зависимости от заголовка Accept: клиента, он может быть более конкретным, чем атрибут media_type рендерера, и может включать параметры медиатипа.  Например, "application/json; nested=true".
Необязательно. Если предоставляется, то это словарь контекстной информации, предоставляемой представлением.
По умолчанию сюда входят следующие ключи: view , request , response , args , kwargs.
Пример¶
Ниже приведен пример рендеринга обычного текста, который вернет ответ с параметром data в качестве содержимого ответа.
from django.utils.encoding import smart_text
from rest_framework import renderers
class PlainTextRenderer(renderers.BaseRenderer):
    media_type = 'text/plain'
    format = 'txt'
    def render(self, data, media_type=None, renderer_context=None):
        return smart_text(data, encoding=self.charset)
Настройка набора символов¶
По умолчанию предполагается, что классы рендереров используют кодировку UTF-8.  Чтобы использовать другую кодировку, установите атрибут charset на рендерере.
class PlainTextRenderer(renderers.BaseRenderer):
    media_type = 'text/plain'
    format = 'txt'
    charset = 'iso-8859-1'
    def render(self, data, media_type=None, renderer_context=None):
        return data.encode(self.charset)
Обратите внимание, что если класс renderer возвращает строку unicode, то содержимое ответа будет преобразовано в байтстринг классом Response, с атрибутом charset, установленным на renderer, используемом для определения кодировки.
Если рендерер возвращает байтстринг, представляющий необработанное двоичное содержимое, следует установить значение charset None , что обеспечит отсутствие в заголовке ответа Content-Type значения charset.
В некоторых случаях вы также можете установить атрибут render_style на 'binary'.  Это также гарантирует, что просматриваемый API не будет пытаться отобразить двоичное содержимое в виде строки.
class JPEGRenderer(renderers.BaseRenderer):
    media_type = 'image/jpeg'
    format = 'jpg'
    charset = None
    render_style = 'binary'
    def render(self, data, media_type=None, renderer_context=None):
        return data
Расширенное использование рендеринга¶
Вы можете делать довольно гибкие вещи, используя рендереры фреймворка REST. Некоторые примеры…
Предоставление плоских или вложенных представлений из одной и той же конечной точки, в зависимости от запрашиваемого типа носителя.
Предоставление как обычных веб-страниц HTML, так и ответов API на основе JSON с одних и тех же конечных точек.
Укажите несколько типов представления HTML для использования клиентами API.
Недоопределение медиатипа рендерера, например, использование
media_type = 'image/*', и использование заголовкаAcceptдля изменения кодировки ответа.
Различное поведение в зависимости от типа СМИ¶
В некоторых случаях вы можете захотеть, чтобы ваше представление использовало различные стили сериализации в зависимости от принятого медиатипа.  Если вам нужно сделать это, вы можете обратиться к request.accepted_renderer, чтобы определить согласованный рендерер, который будет использоваться для ответа.
Например:
@api_view(['GET'])
@renderer_classes([TemplateHTMLRenderer, JSONRenderer])
def list_users(request):
    """
    A view that can return JSON or HTML representations
    of the users in the system.
    """
    queryset = Users.objects.filter(active=True)
    if request.accepted_renderer.format == 'html':
        # TemplateHTMLRenderer takes a context dict,
        # and additionally requires a 'template_name'.
        # It does not require serialization.
        data = {'users': queryset}
        return Response(data, template_name='list_users.html')
    # JSONRenderer requires serialized data as normal.
    serializer = UserSerializer(instance=queryset)
    data = serializer.data
    return Response(data)
Недоопределение типа носителя¶
В некоторых случаях вы можете захотеть, чтобы рендерер обслуживал ряд типов медиа. В этом случае вы можете не указывать типы медиа, на которые он должен реагировать, используя значение media_type, например image/* , или */*.
Если вы недоопределили медиатип рендерера, вы должны убедиться, что указали медиатип явно при возврате ответа, используя атрибут content_type.  Например:
return Response(data, content_type='image/png')
Проектирование типов носителей информации¶
Для целей многих Web API может быть достаточно простых ответов JSON с гиперссылками.  Если вы хотите полностью внедрить RESTful дизайн и HATEOAS, вам необходимо более детально продумать дизайн и использование ваших типов носителей.
В :doc:`the words of Roy Fielding <https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven>`** , «REST API должен потратить почти все свои описательные усилия на определение типа(ов) медиа, используемых для представления ресурсов и управления состоянием приложения, или на определение расширенных имен отношений и/или гипертекстовой разметки для существующих стандартных типов медиа».
Хорошими примерами пользовательских типов медиа являются использование GitHub пользовательского типа медиа application/vnd.github+json и одобренная IANA гипермедиа на основе JSON application/vnd.collection+json Майка Амундсена.
Представления ошибок HTML¶
Обычно рендерер ведет себя одинаково независимо от того, имеет ли он дело с обычным ответом или с ответом, вызванным возникшим исключением, например, исключением Http404 или PermissionDenied, или подклассом APIException.
Если вы используете TemplateHTMLRenderer или StaticHTMLRenderer и возникает исключение, поведение немного отличается, и зеркально отражает Django’s default handling of error views.
Исключения, возникающие и обрабатываемые устройством рендеринга HTML, будут пытаться отобразить с помощью одного из следующих методов, в порядке старшинства.
Загрузка и рендеринг шаблона с именем
{status_code}.html.Загрузка и рендеринг шаблона с именем
api_exception.html.Вывод кода статуса HTTP и текста, например, «404 Not Found».
Шаблоны будут отображаться с помощью RequestContext, который включает в себя ключи status_code и details.
Примечание: Если DEBUG=True, то вместо отображения кода статуса HTTP и текста будет отображаться стандартная страница ошибки трассировки Django.
Пакеты сторонних производителей¶
Также доступны следующие пакеты сторонних производителей.
YAML¶
REST framework YAML обеспечивает поддержку парсинга и рендеринга YAML. Ранее он был включен непосредственно в пакет REST framework, а теперь поддерживается как сторонний пакет.
Установка и настройка¶
Установите с помощью pip.
$ pip install djangorestframework-yaml
Измените настройки фреймворка REST.
REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework_yaml.parsers.YAMLParser',
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_yaml.renderers.YAMLRenderer',
    ],
}
XML¶
REST Framework XML предоставляет простой неформальный формат XML. Ранее он был включен непосредственно в пакет REST framework, а теперь вместо этого поддерживается как сторонний пакет.
Установка и настройка¶
Установите с помощью pip.
$ pip install djangorestframework-xml
Измените настройки фреймворка REST.
REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework_xml.parsers.XMLParser',
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_xml.renderers.XMLRenderer',
    ],
}
JSONP¶
REST framework JSONP обеспечивает поддержку рендеринга JSONP. Ранее он был включен непосредственно в пакет REST framework, а теперь поддерживается как сторонний пакет.
Предупреждение : Если вам требуются междоменные AJAX-запросы, вам следует использовать более современный подход CORS в качестве альтернативы JSONP. Более подробную информацию смотрите в CORS documentation.
Подход jsonp по сути является взломом браузера, и представляет собой only appropriate for globally readable API endpoints <https://stackoverflow.com/questions/613962/is-jsonp-safe-to-use>`** , где ``GET` запросы являются неаутентифицированными и не требуют никаких разрешений пользователя.
Установка и настройка¶
Установите с помощью pip.
$ pip install djangorestframework-jsonp
Измените настройки фреймворка REST.
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_jsonp.renderers.JSONPRenderer',
    ],
}
MessagePack¶
MessagePack - это быстрый, эффективный формат двоичной сериализации. Juan Riaza поддерживает пакет djangorestframework-msgpack, который обеспечивает поддержку MessagePack renderer и parser для REST framework.
XLSX (конечные точки бинарных электронных таблиц)¶
XLSX - это самый популярный в мире формат двоичных электронных таблиц. Tim Allen из The Wharton School поддерживает :doc:`drf-renderer-xlsx <https://github.com/wharton/drf-renderer-xlsx>`** , который рендерит конечную точку как электронную таблицу XLSX, используя OpenPyXL, и позволяет клиенту загрузить ее. Электронные таблицы могут быть стилизованы на основе каждого представления.
Установка и настройка¶
Установите с помощью pip.
$ pip install drf-renderer-xlsx
Измените настройки фреймворка REST.
REST_FRAMEWORK = {
    ...
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
        'drf_renderer_xlsx.renderers.XLSXRenderer',
    ],
}
Чтобы избежать потоковой передачи файла без имени файла (который браузер часто принимает по умолчанию за файл «download» без расширения), нам нужно использовать миксин для переопределения заголовка Content-Disposition. Если имя файла не указано, то по умолчанию будет использоваться export.xlsx. Например:
from rest_framework.viewsets import ReadOnlyModelViewSet
from drf_renderer_xlsx.mixins import XLSXFileMixin
from drf_renderer_xlsx.renderers import XLSXRenderer
from .models import MyExampleModel
from .serializers import MyExampleSerializer
class MyExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
    queryset = MyExampleModel.objects.all()
    serializer_class = MyExampleSerializer
    renderer_classes = [XLSXRenderer]
    filename = 'my_export.xlsx'
CSV¶
Значения, разделенные запятыми, - это формат табличных данных в виде обычного текста, который можно легко импортировать в приложения электронных таблиц. Mjumbe Poe поддерживает пакет djangorestframework-csv, который обеспечивает поддержку рендеринга CSV для фреймворка REST.
UltraJSON¶
UltraJSON - это оптимизированный кодировщик JSON на языке C, который может значительно ускорить рендеринг JSON. Adam Mertz поддерживает :doc:`drf_ujson2 <https://github.com/Amertz08/drf_ujson2>`**, форк ныне не поддерживаемого :doc:`drf-ujson-renderer <https://github.com/gizmag/drf-ujson-renderer>`**, который реализует рендеринг JSON, используя пакет UJSON.
CamelCase JSON¶
djangorestframework-camel-case предоставляет рендереры и парсеры JSON в верблюжьем регистре для фреймворка REST. Это позволяет сериализаторам использовать имена полей с подчеркиванием в стиле Python, но отображать их в API как имена полей в верблюжьем регистре в стиле Javascript. Поддерживается Vitaly Babiy.
Pandas (CSV, Excel, PNG)¶
Django REST Pandas предоставляет сериализатор и рендереры, которые поддерживают дополнительную обработку и вывод данных через Pandas DataFrame API.  Django REST Pandas включает рендереры для CSV файлов в стиле Pandas, рабочих книг Excel (как .xls, так и .xlsx ), и ряда other formats. Он поддерживается S. Andrew Sheppard как часть wq Project.
LaTeX¶
Rest Framework Latex предоставляет рендерер, который выводит PDF-файлы с использованием Laulatex. Он поддерживается Pebble (S/F Software).