Руководство по API Django REST framework (8): рендеринг

задняя часть Python API Django

Руководство по API платформы Django REST (1): запросы
Руководство по API платформы Django REST (2): ответы
Руководство по API платформы Django REST (3): представления
Руководство по API платформы Django REST (4): общие представления
Руководство по API платформы Django REST (5): наборы представлений
Руководство по API платформы Django REST (6): Маршрутизация
Руководство по API платформы Django REST (7): анализ
Руководство по API Django REST framework (8): рендеринг

Официальная оригинальная ссылка

оказывать

Платформа REST включает в себя ряд встроенных классов рендеринга, которые позволяют вам возвращать ответы с различными типами мультимедиа. Также поддерживает пользовательские рендереры.

Как определить, какой рендерер использовать

Набор визуализаторов представления всегда определяется как список классов. Когда представление вызывается, платформа REST анализирует содержимое запроса и определяет наиболее подходящий модуль визуализации для удовлетворения запроса. Основной процесс контент-анализа состоит в изученииAcceptзаголовок, чтобы определить тип мультимедиа, который он ожидает в ответе. В качестве альтернативы сделайте это явным с суффиксом формата в URL-адресе. Например, URL-адресhttp://example.com/api/users_count.jsonВсегда может возвращать данные JSON.

установить визуализатор

можно использоватьDEFAULT_RENDERER_CLASSESУстановите глобальный набор средств визуализации по умолчанию. Например, следующая настройка будет использовать JSON в качестве основного типа мультимедиа, а также включать API с самоописанием.

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    )
}

Вы также можете использовать на основеAPI​​ViewКласс представления для установки средства визуализации для одного представления или набора представлений.

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 выберет первый модуль визуализации в списке, который будет использоваться для ответа.

Например, если ваш API предоставляет ответы JSON и HTML API с возможностью просмотра, вам может потребоватьсяJSONRendererв качестве средства визуализации по умолчанию, чтобыJSONОтвет отправлен не указанномуAcceptзаголовок клиента.

Если ваш API содержит представления, которые обрабатывают как обычные веб-страницы, так и ответы API по запросу, вы можете рассмотреть возможность добавленияTemplateHTMLRendererУстановите в качестве средства визуализации по умолчанию, чтобы хорошо работать со старыми браузерами, отправляющими неработающие заголовки принятия.

Справочник по API

JSONRenderer

Отобразить данные запроса в виде кодировки utf-8JSON.

Обратите внимание, что стиль по умолчанию включает символы Юникода и отображает ответ в компактном стиле (без лишних пробелов):

{"unicode black star":"★","value":999}

Клиенты могут также включать параметр типа мультимедиа "indent", и в этом случае возвращаемыйJSONбудет с отступом.

Например:Accept: application/json; indent=4.

{
    "unicode black star": "★",
    "value": 999
}

использоватьUNICODE_JSONиCOMPACT_JSONУстановите ключ, чтобы изменить стиль кодирования JSON по умолчанию.

.media_type:application/json

.format:'.json'

.charset:None

TemplateHTMLRenderer

Визуализация данных в формате HTML с использованием стандартных шаблонов Django. В отличие от других рендереров, передаетсяResponseДанные не нужно сериализовать. Кроме того, создайтеResponseможет потребоваться включитьtemplate_nameпараметр.

TemplateHTMLRenderer создастRequestContext,использоватьresponse.dataВ качестве словаря контекста и определяет имя шаблона, используемого для отображения контекста.

Имена шаблонов определяются (в порядке старшинства) по:

  1. Явно передается в ответtemplate_nameпараметр.
  2. Установить явное значение для этого класса.template_nameАтрибуты.
  3. перечислить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чтобы платформа REST возвращала обычные HTML-страницы или возвращала ответы HTML и API из одной конечной точки.

Если вы строите с помощьюTemplateHTMLRendererи другие сайты, похожие на рендереры, вам следует подумать о добавленииTemplateHTMLRendererуказан какrenderer_classesПервый класс в списке, так что даже для отправки некорректныхACCEPT:заголовок, также отдаст ему приоритет.

.media_type:text/html

.format:'.html'

.charset:utf-8

StaticHTMLRenderer

Простой рендерер, который просто возвращает предварительно обработанный HTML. В отличие от других средств визуализации, данные, передаваемые объекту ответа, должны представлять собой строку, представляющую, что следует возвращать.

использовать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чтобы платформа REST возвращала обычные HTML-страницы или возвращала ответы HTML и API из одной конечной точки.

.media_type:text/html

.format:'.html'

.charset:utf-8

BrowsableAPIRenderer

Отображение данных в доступном для просмотра HTML 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, чтобы отобразить содержимое, похожее на администратора:

Этот рендерер работает с веб-API в стиле CRUD, который также должен предоставлять удобный интерфейс для управления данными.

Пожалуйста, обрати внимание,AdminRendererНе работает для представлений, которые вкладывают или перечисляют сериализованные входные данные, поскольку HTML-формы не поддерживают их должным образом.

Уведомление: при наличии правильно настроенногоURL_FIELD_NAME(по умолчаниюurl) имущество,AdminRendererМожет содержать только ссылки на подробные страницы. заHyperlinkedModelSerializer, это так, но дляModelSerializerкласс или обычныйSerializerclass, вы должны убедиться, что это поле включено явно. Например, здесь мы используем модель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>

.media_type:text/html

.format:'.form'

.charset:utf-8

.template:'rest_framework/horizontal/form.html'

MultiPartRenderer

Этот модуль визуализации используется для визуализации данных составной формы HTML. Он подходит не для рендеринга ответов, а для создания тестовых запросов с использованием тестового клиента REST framework и фабрики тестовых запросов.

.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()Параметры метода:

data

запросить данные, поResponse()Устанавливается при создании экземпляра.

media_type=None

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

зависимый от клиентаAccept:заголовок, который можно сравнить с рендереромmedia_typeСвойства являются более конкретными и могут содержать параметры типа носителя. Например"application/json; nested=true".

renderer_context=None

по желанию. Если предоставлено, это словарь контекстной информации, предоставляемой представлением.

По умолчанию это будет включать следующие ключи:view , request , response , args , kwargs.

взять каштан

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

from django.utils.encoding import smart_unicode
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 data.encode(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)

Обратите внимание, что если класс рендерера возвращает строку в Юникоде, содержимое ответа будетResponseкласс приведен к байтовой строке, пожалуйста, установите на рендеререcharsetСвойства используются для определения кодировки.

Если средство визуализации возвращает строку, представляющую необработанное двоичное содержимое, оно должно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 framework, чтобы делать очень гибкие вещи. Например...

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

Создайте свой медиа-тип

Для многих целей веб-API может быть достаточно простого ответа JSON с гиперссылками. Если вы хотите полностью использовать дизайн RESTful и HATEOAS, вам необходимо более подробно рассмотреть дизайн и использование типов носителей.

Просмотр ошибок HTML

Как правило, независимо от того, имеете ли вы дело с обычным ответом или ответом, выдающим исключение (например,Http404илиPermissionDeniedисключение) илиAPIExceptionОтвет, вызванный подклассом средства визуализации, будет иметь такое же поведение.

если вы используетеTemplateHTMLRendererилиStaticHTMLRenderer, и выдает исключение, поведение немного отличается, отражая стандартную обработку представлений ошибок в Django.

Исключения, созданные и обработанные средством визуализации HTML, попытаются выполнить визуализацию с использованием одного из следующих методов (в порядке предпочтения).

  • Загрузите и визуализируйте шаблон{status_code}.html.
  • Загрузите и визуализируйте шаблонapi_exception.html.
  • Отображает коды состояния HTTP и текст, например «404 Not Found».

шаблон будет использоватьRequestContextдля рендеринга, который содержитstatus_codeиdetailsключ.

Примечание: еслиDEBUG = True, вместо кода состояния HTTP и текста отображается стандартная страница трассировки ошибок Django.