Фреймворк Django REST (DRF) в Python — как использовать

В этом руководстве вы узнаете о Django REST Framework и о том, как использовать его для создания простого, но полного RESTful API, управляющего задачами в Python.

Содержание

Введение в фреймворк Django REST

Django REST Framework или DRF — это мощный инструментарий для разработки веб-API в приложениях Django. DRF позволяет быстро создавать RESTful API, предоставляя готовые классы и соглашения.

DRF имеет следующие ключевые особенности:

  • Сериализация: позволяет автоматически преобразовывать модели Django в JSON и наоборот, обеспечивая бесперебойную передачу данных между клиентом и сервером.
  • Маршрутизация URL: DRF обеспечивает маршрутизацию URL, аналогичную маршрутизатору Django, что позволяет эффективно связывать URL-адреса с представлениями API.
  • Аутентификация: DRF предлагает различные методы аутентификации, включая базовую аутентификацию и аутентификацию токенов. Он также поддерживает JWT через сторонний пакет.
  • Разрешение: DRF обеспечивает детальный контроль над разрешениями пользователей.
  • Регулирование/Ограничение скорости: функции регулирования и скорости помогают ограничить количество запросов, которые клиент может сделать в течение определенного периода времени.
  • Пагинация: DRF обеспечивает встроенную поддержку пагинации больших наборов данных в ответах API.
  • API с возможностью просмотра: DRF имеет удобный HTML-интерфейс для тестирования и изучения API непосредственно из браузера.

Установка пакета Django REST Framework

Сначала установите фреймворк Django REST в виртуальную среду проекта:

pip install djangorestframework

Во-вторых, обновите файл requirements.txt:

pip freeze > requirements.txt

В-третьих, зарегистрируйте приложение rest_framework в settings.py проекта:

INSTALLED_APPS = [
    ...
    'rest_framework', 
    ...
]

Создание нового приложения на основе Django REST

Создайте новый каталог с именем api в каталоге проекта для размещения кода API:

mkdir api

Во-вторых, создайте три файла Python внутри каталога api:

  • serializers.py – предоставляет сериализатор, который преобразует модели Django в формат JSON и наоборот.
  • views.py – содержит представления API, аналогичные представлениям приложения Django.
  • urls.py – определяет конечную точку API, которая сопоставляется с представлениями API.

В-третьих, добавьте API в INSTALLED_APPS в файле settings.py проекта:

INSTALLED_APPS = [
    ...
    'api',
    ...
]

Мы создадим API со следующими конечными точками:

Конечные точки HTTP Verb Описание
API/v1/todos/ GET Вернуть все задачи
API/v2/todos/ POST Создать новую задачу
API/v2/todos/1 GET Вернуть задачу с идентификатором 1
API/v1/todos/1 PATCH Обновить задачу с идентификатором 1
API/v1/todos/1 DELETE Удалить задачу с идентификатором 1

Создание класса сериализатора

Классы сериализаторов позволяют сериализовать экземпляры моделей Django в JSON и наоборот.

Ниже определяется класс сериализатора TodoSerializer в файле serializers.py, который сериализует экземпляр Todo в JSON и наоборот:

from rest_framework import serializers
from todo.models import Todo

class TodoSerializer(serializers.ModelSerializer):
    user = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = Todo
        fields =('id', 'title', 'completed', 'user')

Как это работает.

Сначала импортируем модуль сериализаторов из пакета rest_framework:

from rest_framework import serializers

Во-вторых, импортируйте модель Todo из модуля моделей приложения Todo:

from todo.models import Todo

В-третьих, определите класс TodoSerializer, который расширяет класс serializers.ModelSerializer:

class TodoSerializer(serializers.ModelSerializer):
    ...

ModelSerializer предоставляет быстрый способ определения класса сериализатора с полями, соответствующими полям модели.

Внутри класса TodoSerializer определите класс Meta, который инициализирует:

  • model – определяет модель Todo.
  • fields – указывает список полей для сериализатора. Если сериализатор использует все поля модели, вы можете использовать ‘__all__’ вместо этого, например:
fields = '__all__'

Поскольку модель Todo связана с моделью User, мы указываем атрибут user как StringRelatedField() и устанавливаем его параметр на read_only. Это означает, что задача будет иметь строковое представление пользователя, которое в данном случае является именем пользователя.

Параметр read_only позволяет сериализатору только читать модель User. Другими словами, сериализатор не сможет обновить модель User.

Помимо StringRelatedField, DRF предоставляет другие типы связанных полей, как показано в следующей таблице:

Поле Описание
PrimaryKeyRelatedField Представляет связанную модель в качестве первичного ключа.
HyperlinkedRelatedField Представляет связанную модель в виде гиперссылки.
SlugRelatedField Представляет соответствующую модель как одно из ее полей.
HyperlinkedIdentityField Представляет связанную модель в виде гиперссылки на поле идентификации.

Поскольку мы завершили определение класса Serializer, давайте используем его для сериализации модели Todo с помощью класса TodoSerializer в оболочке Django.

Сериализация данных

Сначала запустите Django Shell из терминала:

python manage.py shell

Во-вторых, импортируйте модель Todo и класс TodoSerializer:

>>> from api.serializers import TodoSerializer
>>> from todo.models import Todo

В-третьих, получите Todo с идентификатором 1:

>> todo = Todo.objects.get(id=1)
>>> todo
<Todo: Learn Python>

В-четвертых, создайте новый экземпляр TodoSerializer с моделью Todo и получите доступ к атрибуту data:

>>> serializer = TodoSerializer(todo)
>>> serializer.data
{'id': 1, 'title': 'Learn Python', 'completed': False, 'user': 'john'}

Объект TodoSerialzier сериализует модель задач в формат JSON.

Создание класса представления API

Ниже приведены определения классов представлений API в файле views.py:

from rest_framework import generics
from .serializers import TodoSerializer
from todo.models import Todo


class TodoList(generics.ListCreateAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


class TodoDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer

Как это работает.

Сначала импортируем дженерики из rest_framework:

from rest_framework import generics

Универсальные типы предоставляют различные базовые классы представлений, такие как ListCreateAPIView и RetrieveUpdateDestroyAPIView.

Во-вторых, импортируйте TodoSerializer из сериализаторов приложения API и модель Todo из моделей приложения Todo:

from .serializers import TodoSerializer
from todo.models import Todo

В-третьих, определите класс TodoList, который расширяет класс ListCreateAPIView. Класс TodoList отвечает за две задачи:

  • Перечислите все задачи.
  • Создайте новую задачу.
class TodoList(generics.ListCreateAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

В классе TodoList укажите набор запросов, используемый для возврата всех задач, и serializer_class, используемый для сериализации/десериализации экземпляров Todo. Метод perform_create() класса TodoSerializer вызывается автоматически при сохранении нового экземпляра Todo.

Поскольку каждому экземпляру Todo необходим экземпляр User, мы назначаем пользователя из HTTP-запроса(request) атрибуту user экземпляра Todo перед его сохранением в базе данных.

Наконец, определите класс TodoDetail, который расширяет класс RetrieveUpdateDestroyAPIView:

class TodoDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer

Класс TodoDetail отвечает за следующие операции:

  • Получить задачу по идентификатору.
  • Обновить существующую задачу.
  • Уничтожить(или удалить) задачу.

В классе TodoDetail нам также необходимо определить queryset и serializer_class.

Определение конечных точек API

Ниже приведены определения конечных точек API в urls.py приложения API:

from django.urls import path

from .views import TodoList, TodoDetail

urlpatterns = [
    path('todos/', TodoList.as_view(), name='todo_list'),
    path('todos/<int:pk>/', TodoDetail.as_view(), name='todo_detail'),
]

Взаимодействие с API с использованием Browsable API

Django REST Framework поддерживает создание удобных для пользователя HTML-страниц всех ресурсов при запросе HTML-формата.

Эти страницы позволяют вам легко просматривать API и отправлять данные в конечные точки API с помощью POST, PUT, PATCH и DELETE.

Получение всех задач

Откройте конечную точку http://localhost:8000/api/v1/todos/, и вы увидите следующую страницу.

Пример получения всех задач

Открывая api/v1/todos/ в веб-браузере, вы выполняете запрос GET к конечной точке. Страница возвращает список todos в красиво отформатированной HTML-странице.

Чтобы получить необработанный формат JSON, укажите формат запроса GET, щелкнув пункт меню json в кнопке GET, как показано на следующем рисунке:

Получение необработанного формата JSON

API вернет необработанный JSON:

[{"id":1,"title":"Learn Python","completed":false,"user":"john"},{"id":2,"title":"Study Django","completed":false,"user":"john"},{"id":3,"title":"Master Django REST API","completed":false,"user":"john"}]

Если в вашем веб-браузере установлено расширение для просмотра JSON, вы можете увидеть понятный человеку формат JSON следующим образом:

[
  {
    "id": 1,
    "title": "Learn Python",
    "completed": false,
    "user": "john"
  },
  {
    "id": 2,
    "title": "Study Django",
    "completed": false,
    "user": "john"
  },
  {
    "id": 3,
    "title": "Master Django REST API",
    "completed": false,
    "user": "john"
  }
]

Создание новой задачи

Откройте конечную точку /api/v1/todos/. Но на этот раз мы отправим запрос POST вместо запроса GET.

Сначала введите информацию о задачах:

Введение информации о задачах

Во-вторых, нажмите кнопку POST, и вы получите следующий ответ:

Ответ после нажатия кнопки POST

API создает новую задачу с идентификатором 4. Кроме того, пользователь — это тот, под чьим именем вы в данный момент вошли в систему.

Обратите внимание, что вам необходимо войти на сайт администратора как пользователь, например, john, чтобы метод perform_create() TodoList мог получить информацию о пользователе из запроса.

Получение конкретной задачи

Откройте конечную точку /api/v1/todos/4/, чтобы получить подробную информацию о задаче с идентификатором 4:

Пример получения конкретной задачи

В этом случае мы делаем запрос GET к конечной точке API /api/v1/todos/4/

Обновление задачи

Страница обновления задачи также является страницей, на которой отображаются подробные сведения о задаче.

Откройте конечную точку /api/v1/todos/4/, чтобы получить подробную информацию о задаче с идентификатором 4, и прокрутите страницу вниз до HTML-формы:

Пример обновления задачи

Во-вторых, измените некоторые значения Todo JSON и нажмите кнопку PUT, чтобы отправить запрос PUT, и вы получите следующий ответ:

Ответ после нажатия кнопки PUT

Удаление задачи

Откройте конечную точку, чтобы просмотреть задачу с идентификатором 4: /api/v1/todos/4/ и нажмите кнопку «Удалить»:

Пример удаления задачи

Будет выведен запрос на подтверждение удаления:

Запрос на удаление

Если вы нажмете кнопку «Delete», вы получите следующий ответ:

Ответ после нажатия кнопки Delete

API отправил запрос DELETE к конечной точке и вернул HTTP-статус 204, указывающий на то, что задача была успешно удалена.

Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *