Курс по Django: https://stepik.org/a/183363
На предыдущем
занятии мы с вами создали простой проект на Django, установили Django REST Framework и реализовали
тестовый пример для API. Для этого нам нужно было сделать три шага:
-
создать
представление WomenAPIView;
-
создать
сериализатор WomenSerializer;
-
прописать маршрут
path('api/v1/womenlist/', WomenAPIView.as_view())
Причем, обратите
внимание, как записывается URL-адрес для API-запросов.
Сначала префикс api, затем, версия API и только потом
некоторое название womenlist, отражающее суть запроса. Рекомендуется
придерживаться такого правила.
Наверное,
сейчас, глядя на первые два компонента (WomenAPIView и WomenSerializer)
возникает некоторое непонимание их назначения и порядка работы? Поэтому данное
занятие я решил посвятить детальному объяснению работы представлений в Django REST Framework. Для этого мы
пока оставим сериализатор в стороне и наше приложение будет состоять из двух
компонент: представления и маршрутизации.
Первым шагом (в
файле women/views.py) мы определим
класс WomenAPIView
на основе базового APIView. Это класс, на основе которого создаются все другие
классы представлений в DRF и он содержит лишь некоторый базовый
функционал. Полный список классов представлений можно посмотреть на странице
официальной документации:
https://www.django-rest-framework.org/api-guide/generic-views/
Импортируем
класс APIView вместе с классом Response для формирования ответа в виде JSON:
from rest_framework.response import Response
from rest_framework.views import APIView
А, затем, переопределим
WomenAPIView, например, так:
class WomenAPIView(APIView):
def get(self, request):
return Response({'title': 'Angelina Jolie'})
Мы сделали
простейшую реализацию API-запроса без какого-либо сериализатора. Здесь
описан один метод get(), который отвечает за GET-запрос и
возвращает фиксированные данные в виде JSON-строки.
Давайте
посмотрим, как это будет работать. Запустим тестовый веб-сервер:
python manage.py runserver
и отправим GET-запрос с
помощью браузера:
http://127.0.0.1:8000/api/v1/womenlist/
видим ответ в
виде JSON-строки.
А что будет,
если по этому же адресу будет отправлен POST-запрос? Здесь
сразу возникает вопрос, как это сделать, так как браузер через адресную строку
формирует GET, а не POST-запросы. На мой
взгляд удобнее всего воспользоваться программой, которая позволяет посылать
различные запросы по указанным URL-адресам. Таких программ множество. Я
воспользуюсь довольно распространенным приложением Postman, которое можно
скачать по адресу:
https://www.postman.com/downloads/
После запуска мы
увидим окно, где можно указать URL-адрес назначения и тип запроса:
При POST-запросе нам
возвращается JSON-строка с
сообщением «Метод POST не разрешен». Этот ответ был автоматически
сгенерирован базовым классом APIView, который берет на себя обработку
типовых ошибок при запросах, что очень удобно.
Давайте добавим
в класс метод post, например, так:
class WomenAPIView(APIView):
def get(self, request):
return Response({'title': 'Angelina Jolie'})
def post(self, request):
return Response({'title': 'Jennifer Shrader Lawrence'})
И снова выполним
POST-запрос. Теперь
видим JSON-строку:
{"title":
"Jennifer Shrader Lawrence"}
Конечно, все это
тестовые примеры и реальный API-запрос, как правило, ожидает получения
данных из таблиц БД или, какого-либо другого хранилища. В рамках нашего класса WomenAPIView это можно было
бы сделать, следующим образом (для GET-запроса):
def get(self, request):
lst = Women.objects.all().values()
return Response({'posts': list(lst)})
Мы здесь
выбираем все записи из таблицы women, преобразуем их к списку и возвращаем в
виде JSON-строки. Если
теперь выполнить GET-запрос через Postman, то получим всю
информацию из БД.
Аналогично
поправим и POST-запрос. Как вы
знаете, он используется для добавления новой информации. В нашем случае – это
будет создание новой записи в таблице women:
def post(self, request):
post_new = Women.objects.create(
title=request.data['title'],
content=request.data['content'],
cat_id=request.data['cat_id']
)
return Response({'post': model_to_dict(post_new)})
Здесь
возвращается JSON-строка с
содержимым добавленной записи. Для этого мы должны объект post_new преобразовать в
словарь, например, с помощью функции model_to_dict фреймворка Django:
from django.forms.models import model_to_dict
Перейдем в
программу Postman. Выберем POST-запрос, во
вкладке «Body» отметим пункт
«raw», укажем, что
это будет JSON-формат и
пропишем следующие данные для отправки на сервер:
{
"title": "Sergei",
"content": "Sergei Balakirev",
"cat_id": 2
}
Обратите
внимание, что данные для нашего API должны
отправляться в JSON-формате, а не как простые текстовые данные, то
есть, заголовок должен иметь обозначение «application/json». Все взаимодействие
и при получении данных и при отправке происходит по умолчанию в JSON-формате. Про
это не нужно забывать.
Нажимаем
отправить «Send» и видим, что
запись была успешно добавлена в БД. Разумеется, если указать неполные данные,
например, убрать заголовок, то у нас возникнут ошибки при выполнении метода post(). То есть,
здесь данные не проверяются на валидность модели. Но нам эту проверку делать
нет смысла, т.к. при работе с моделями применяются соответствующие классы
представлений, где эта обработка уже встроена. Здесь я лишь показываю принцип
работы представлений в Django REST Framework.
Помимо методов get() и post() можно
прописывать и другие для обработки соответствующих типов запросов:
-
get() – вызывается
при GET-запросах;
-
post() – вызывается
при POST-запросах;
-
put() – вызывается
при PUT-запросах;
-
patch() – вызывается
при PATCH-запросах;
-
delete() – вызывается
при DELETE-запросах.
У вас здесь
может возникнуть вопрос, а как одно и то же представление для одного и того же URL-адреса
«понимает», какой из методов следует вызывать, когда приходит какой-либо запрос
от клиента? В действительности, все просто. Когда клиент формирует запрос, то в
его заголовке прописывается тип этого запроса: GET, POST, DELETE, PUT и т.п. Затем,
алгоритм, заложенный в представления DRF автоматически вызывает метод,
связанный с поступившим запросом. Если нужный метод не находится, то клиенту
возвращается JSON-строка с
сообщением, что метод не разрешен.
Итак, на этом
занятии мы с вами создали простейшее представление на основе базового класса APIView и сами, вручную
создавали сериализованные данные в виде JSON-ответа. Целью данного
занятия было показать, как на низком уровне без сериализаторов можно
самостоятельно формировать данные и реализовывать простейшие API с одним классом
представления. На следующем занятии мы сделаем очередной шаг в понимании работы
Django REST Framework и также
детально опишем и добавим простой сериализатор в наше приложение.
Курс по Django: https://stepik.org/a/183363