Разобраться с базовыми принципами работы с API вам поможет наш простой Django-проект Kittygram: управление котиками.
В этом проекте упрощено всё, что можно было упростить: он подготовлен для изучения базовых принципов API. Сложный полноценный проект ожидает вас впереди, а пока потренируемся на кошках.
Обратите внимание на библиотеку djangorestframework
, именно она поможет быстро и гибко настроить API проекта. Загляните в файл настроек settings.py: проверьте, что приложение cats и библиотека rest_framework добавлены в INSTALLED_APPS.
А что внутри?
В Kittygram описана простая модель — Cat
. В ней есть три поля:
# kittygram/cats/models.py
class Cat(models.Model):
name = models.CharField(max_length=16)
color = models.CharField(max_length=16)
birth_year = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.name
В файле urls.py настроена обработка адреса cats/
: запросы к этому URL направляются во view-функцию cat_list()
приложения cats:
# kittygram/kittygram/urls.py
from django.urls import path
from .views import cat_list
urlpatterns = [
path('cats/', cat_list, name='cat_list'),
]
Файл views.py содержит единственную view-функцию cat_list()
. Обратите внимание на декоратор @api_view
, именно он настраивает обычную view-функцию для работы с API: например, в нём указываются типы запросов, которые должна обрабатывать view-функция. В следующем уроке мы разберёмся, что это за декоратор и чем ещё он хорош.
# kittygram/cats/views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Cat
from .serializers import CatSerializer
# View-функция cat_list() будет обрабатывать только запросы GET и POST,
# запросы других типов будут отклонены,
# так что в теле функции их можно не обрабатывать
@api_view(['GET', 'POST'])
def cat_list(request):
if request.method == 'POST':
serializer = CatSerializer(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)
cats = Cat.objects.all()
serializer = CatSerializer(cats, many=True)
return Response(serializer.data)
Откройте в редакторе файл serializers.py, там описан сериализатор CatSerializer
:
# kittygram/cats/serializers.py
from rest_framework import serializers
from .models import Cat
class CatSerializer(serializers.ModelSerializer):
class Meta:
model = Cat
fields = '__all__'
Сериализатор CatSerializer связывает модель и view-класс: он берёт информацию о типах данных из модели, указанной в поле model
. Остаётся только указать в fields
те поля, которые надо сериализовать, — и система заработает.
Проверяем работу Kittygram
После развёртывания проект Kittygram полностью готов к работе. Запустите его и сделайте к нему запрос через Postman.
- Запустите приложение Kittygram командой
python manage.py runserver
. - Запустите приложение Postman, в качестве целевого URL укажите
http://127.0.0.1:8000/cats/
. - Отправьте GET-запрос.
В ответ вернётся пустой JSON-объект. Это нормально, ведь в базе данных пока пусто:
Первый котик в Kittygram
Чтобы создать в БД первую запись с котиком, выполните POST-запрос к проекту и передайте поля name
, color
и birth_year
:
Обратите внимание, что поля нужно передавать в теле (англ. body) POST-запроса. А в Postman в соответствующем разделе должны быть выбраны опции raw и JSON.
Проверьте ответ: если запрос обработан корректно, должен вернуться статус-код 201 Created и JSON с только что созданным объектом.
Получилось? Отлично!
Сделайте ещё один POST-запрос, создайте запись для второго котика.
Повторно выполните GET-запрос на тот же URL, в ответ вам вернётся список из существующих в базе данных записей.
Время делать ошибки: 400 Bad Request
Проверьте, что будет, если передать данные в неправильном формате: например, вместо целочисленного значения в поле birth_year
передайте данные в формате месяц.год
.
При валидации данных сериализатор обнаружит ошибку, и в ответ вернётся вот такой JSON:
{
"birth_year": [
"A valid integer is required."
]
}
Обратите внимание на статус-код ответа: 400 Bad Request. Поле birth_year
ожидает данные в формате Integer (целое число), а полученные в запросе данные можно привести только к float. В результате запрос не прошёл валидацию и запись не была создана.
Измените запрос: укажите год в формате Integer и повторите попытку. На этот раз всё должно пройти гладко.
Ошибка 405 Method Not Allowed
В декораторе view-функции cat_list()
указано, что она должна обрабатывать запросы GET или POST: можно только создавать и запрашивать данные.
@api_view(['GET', 'POST'])
def cat_list(request):
...
При попытке удалить запись методом DELETE вернётся сообщение об ошибке: 405 Method Not Allowed.
{
"detail": "Method \"DELETE\" not allowed."
}
Настройка полей в ответе
При запросе к API пользователю не понадобится id котика. Хорошо бы убрать это поле из JSON-ответа.Список полей, передаваемых в ответ, описывается в сериализаторе, в поле fields
. Вместо записи fields = '__all__'
явно перечислите обрабатываемые поля.
# Обновлённый kittygram/cats/serializers.py
from .models import Cat
from rest_framework import serializers
class CatSerializer(serializers.ModelSerializer):
class Meta:
model = Cat
fields = ('id', 'name', 'color', 'birth_year')
Сделайте GET-запрос на эндпоинт http://127.0.0.1:8000/cats/
и проверьте, что всё работает и ответ не изменился.Уберите id
из списка полей, и ваш API перестанет отправлять ненужные данные клиенту.
# Обновлённый kittygram/cats/serializers.py
from .models import Cat
from rest_framework import serializers
class CatSerializer(serializers.ModelSerializer):
class Meta:
model = Cat
fields = ('name', 'color', 'birth_year')
Ещё раз сделайте GET-запрос для получения полного списка котиков и посмотрите, как изменилась выдача:
...
{
"name": "Леопольд",
"color": "Рыжий",
"birth_year": 1975
}
...
Отлично! Мы избавились от ненужного поля в выдаче.