training-web.ruГлавнаяКатегорииО насКарта сайтаПоискТёмная тема

Категории

Запросы и ответы в django-rest-framework

Создано: 09 июня 2019Автор: Егор Астапов2034 просмотраСложность: легкий

Запросы и ответы в django-rest-framework. Я решил перевести официальное руководство. Оригинал страницы Tutorial 2: Requests and Responses. Углубляемся в ядро DRF.

Request (запрос) objects

Rest framework представляет объект Request, который расширяет обычный Http-запрос и обеспечивает более гибкий синтаксический анализ запроса. Основной функциональностью объекта Request является request.data, который аналогичен request.POST, но более полезен для работы с веб-API.


# Обрабатывает только данные формы.  
# Работает только для метода "POST".
request.POST 

# Обрабатывает произвольные данные.  
# Работает для методов "POST", " PUT " и "PATCH".
request.data  

Response (ответ) objects

Rest framework также вводит объект ответа, который является типом ответа шаблона, который принимает неупорядоченное содержимое и использует согласование содержимого для определения правильного типа содержимого для возврата клиенту. Вы можете поместить в Response свой словарь.


# Отображает тип содержимого по запросу клиента.
return Response(data)

Status codes

Использование числовых кодов статуса HTTP в ваших представлениях не всегда делает очевидным чтение, и легко не заметить, если вы получите неправильный код ошибки. Rest framework предоставляет более явные идентификаторы для каждого кода состояния, например HTTP_400_BAD_REQUEST в модуле status. Это хорошая идея использовать их повсюду, а не использовать числовые идентификаторы.

Перенос представлений API

Rest framework предоставляет две обёртки, которые можно использовать для записи представлений API.

  • Декоратор @api_view для работы с представлениями на основе функций.
  • Класс APIView для работы с представлениями на основе классов.

Эти обёртки предоставляют некоторые функциональные возможности. Вы получите экземпляры Request в вашем представлении, и добавление контекста к объектам ответ так, что согласование содержания может быть выполнено.

Обертки также обеспечивают поведение такое как возврат 405 Method Not Allowed (не разрешенных ответов) когда это необходимо, и обработку любого исключения ParseError, которое возникает при доступе к request.data при переданных неправильных данных.

Собираю все в кучу

Хорошо, давайте начнем использовать эти новые компоненты, чтобы написать несколько представлений.

Нам не нужен наш класс JSONResponse в views.py больше, так что вперед и удалите это. Как только это будет сделано, мы можем выполнить рефакторинг наших представлений.


from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    List all code snippets, or create a new snippet.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Наше представление экземпляра является улучшением по сравнению с предыдущим примером. Это немного более лаконично, и код теперь очень похож на то, как если бы мы работали с API Forms. Мы также используем именованные коды статуса, что делает значения ответа более очевидными.

Вот представление для отдельного фрагмента, в views.py модуль.


@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Все это должно быть очень знакомо - это не сильно отличается от работы с обычными представлениями Django.

Обратите внимание, что мы больше не связываем наши запросы или ответы с данным типом контента. request.data может обрабатывать входящие запросы json, но также может обрабатывать и другие форматы. Аналогично мы возвращаем объекты ответа с данными, но разрешаем Rest framework рендерить наш ответ в правильном типе для нас.

Добавление дополнительных суффиксов формата в наши URL-адреса

Чтобы воспользоваться тем, что наши ответы больше не привязаны к одному типу контента, давайте добавим поддержку суффиксов формата в наши конечные точки API. Использование суффиксов формата дает нам правила, которые явно ссылаются на данный формат, и означает, что наш API сможет обрабатывать URL-адреса, такие как http://example.com/api/items/4.json-

Начните с добавления в аргумент ключевого слова format в оба представления.


def snippet_list(request, format=None):
#и
def snippet_detail(request, pk, format=None):

Теперь обновите snippets/urls.py файл немного, чтобы добавить набор format_suffix_patterns в дополнение к существующим URL-адресам.


from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    path('snippets/', views.snippet_list),
    path('snippets/', views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)

Нам не обязательно добавлять эти дополнительные шаблоны url, но это дает нам простой и чистый способ ссылки на определенный формат.

Как это выглядит?

Продолжайте и протестируйте API из командной строки, как мы сделали в части 1 учебника. Все работает примерно так же, хотя у нас есть более приятная обработка ошибок, если мы отправляем недопустимые запросы.

Мы можем получить список всех фрагментов как и раньше.


http http://127.0.0.1:8000/snippets/

HTTP/1.1 200 OK
...
[
  {
    "id": 1,
    "title": "",
    "code": "foo = \"bar\"\n",
    "linenos": false,
    "language": "python",
    "style": "friendly"
  },
  {
    "id": 2,
    "title": "",
    "code": "print(\"hello, world\")\n",
    "linenos": false,
    "language": "python",
    "style": "friendly"
  }
]

Мы можем управлять форматом ответа, который мы получаем с помощью заголовка Accept в Header:


# Request JSON
http http://127.0.0.1:8000/snippets/ Accept:application/json 

# Request HTML
http http://127.0.0.1:8000/snippets/ Accept:text/html

Или путем добавления суффикса формата:


# JSON suffix
http http://127.0.0.1:8000/snippets.json

# Browsable API suffix
http http://127.0.0.1:8000/snippets.api

Аналогично, мы можем управлять форматом запроса, который мы отправляем, используя заголовок Content-Type


# POST using form data
http --form POST http://127.0.0.1:8000/snippets/ code="print(123)"

{
  "id": 3,
  "title": "",
  "code": "print(123)",
  "linenos": false,
  "language": "python",
  "style": "friendly"
}

# POST using JSON
http --json POST http://127.0.0.1:8000/snippets/ code="print(456)"

{
    "id": 4,
    "title": "",
    "code": "print(456)",
    "linenos": false,
    "language": "python",
    "style": "friendly"
}

Если вы добавите переключатель --debug к http-запросам выше, вы сможете увидеть тип запроса в заголовках запросов. Теперь перейдите и откройте API в веб-браузере, посетив http://127.0.0.1:8000/snippets/.

Browsability (Просматриваемость)

Поскольку API выбирает тип содержимого ответа на основе запроса клиента, он по умолчанию возвращает HTML-форматированное представление ресурса, когда этот ресурс запрашивается веб-браузером. Это позволяет API возвращать полностью просматриваемое веб-представление HTML.

Наличие веб-просматриваемого API-это огромная победа в юзабилити и упрощает разработку и использование вашего API. Это также значительно снижает барьер для входа для других разработчиков, желающих проверить и работать с вашим API.

См. В разделе browsable api есть дополнительные сведения о функции API-интерфейса для просмотра и настройки его.

Комментарии

реклама