В уроке 3 по созданию API на Django REST Framework, мы рассмотрим создание сериализатора для нашей модели Статьи, а также напишем пример функцию контроллера, для получения JSON данных.
В предыдущем уроке мы создали необходимые модели: Статьи, Категории, поэтому Вы можете ознакомиться с ними в уроке 2: Django REST Framework создание API: Урок: 2, добавление модуля «Блог» и моделей
Давайте в административной части мы создадим для теста пару статей, чтобы в будущем мы их могли увидеть в API:

Я создал 3 примерные статьи для нашего урока.
Базовые примеры (создание JSON без DRF)
Рассмотрим пример, как можно получить сериализованные JSON данные с помощью базового Django:
Внимание, вы можете так не делать, а писать функции контроллера в файле views.py:
Внутри модуля blog, я создам папку views с файлом __init__.py, а внутри папки views я создам файл articles.py

Давайте приступим к написанию функции на основе Django в файле articles.py:
blog/views/articles.py
from modules.blog.models import Article
from django.http import JsonResponse
from django.forms.models import model_to_dict
def home(request, *args, **kwargs):
qs = Article.objects.all().order_by('?').first()
data = {}
if qs:
data = model_to_dict(qs, fields=['title', 'slug', 'short_description', 'full_description', 'category'])
return JsonResponse(data)
Пояснение:
- С помощью встроенных утилит Django попробуем вывести JSON данные.
- В qs забираем одну рандомную статью, с помощью
order_by('?')
- И с помощью встроенной функции
model_to_dict
передаем полученные данные, выбираем необходимые поля и возвращаем в формате JSON:
Добавим в файл __init__.py импорты:
blog/views/__init__.py
from modules.blog.views.articles import home
__all__ = '__all__'
Создадим в модуле blog файл urls.py
blog/urls.py
from django.urls import path
from modules.blog.views import home
urlpatterns = [
path('home/', home),
]
И в главном engine/urls.py подключим наш модульный urls.py
engine/urls.py
"""engine URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('modules.blog.urls')),
]
Перейдем на страницу: 127.0.0.1:8000/api/home/ и посмотрим результат
Результат получился таким:
{"title": "\u0422\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u043e\u043c\u0435\u0440 3", "slug": "test-article-3", "short_description": "\u041a\u0440\u0430\u0442\u043a\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u043e\u043c\u0435\u0440 3", "full_description": "\u041f\u043e\u043b\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u043e\u043c\u0435\u0440 3", "category": 2}
Данные JSON мы получили, но таким образом это все будет создавать неудобно, да и не практично, это было показано для примера. А теперь воспользуемся DRF.
Работа с DRF
Внутри модуля blog я создам папку serializers вместе с __init__.py и articles.py
Получиться должно вот так, но для тех, кто делает все в одном файле, так можно не делать :)

Теперь создадим сам сериализатор на основе нашей модели:
blog/serialziers/articles.py
from rest_framework import serializers
from modules.blog.models import Article
class ArticleSerializer(serializers.ModelSerializer):
"""
Сериализатор для модели "Статьи"
"""
class Meta:
model = Article
fields = '__all__'
Пояснение:
- Сериализатор мы создали, создается он также, как мы бы создавали форму на основе модели.
- В модель прописываем Article
- В полях написал
__all__
для сериализации всех полей.
Добавим импорты в файл __init__.py
blog/serialziers/__init__.py
from modules.blog.serializers.articles import ArticleSerializer
__all__ = '__all__'
Перейдем к созданию контроллера, в views/articles.py
Было:
views/articles.py
from modules.blog.models import Article
from django.http import JsonResponse
from django.forms.models import model_to_dict
def home(request, *args, **kwargs):
qs = Article.objects.all().order_by('?').first()
data = {}
if qs:
data = model_to_dict(qs, fields=['title', 'slug', 'short_description', 'full_description', 'category'])
return JsonResponse(data)
Сделали с помощью инструментария DRF для полученных данных:
views/articles.py
from modules.blog.models import Article
from rest_framework.decorators import api_view
from rest_framework.response import Response
from modules.blog.serializers import ArticleSerializer
@api_view(['GET'])
def home(request, *args, **kwargs):
qs = Article.objects.all().order_by('?').first()
data = {}
if qs:
data = ArticleSerializer(qs).data
return Response(data)
Пояснение:
- Воспользовались декоратором из DRF, который разрешает работу функции только 'GET' запросом.
- Также передаем рандомные данные уже в наш сериализатор, получаем данные с помощью метода
data
- Передаем в
Response
наши данные для вывода.
Посмотрим на результат, перейдя по ссылке 127.0.0.1:8000/api/home/:

Здесь мы видим удобный интерфейс, хорошую читаемость JSON кода.
Давайте немного изменим метод, чтобы мы могли добавить данные в БД с помощью нашего контроллера:
views/articles.py
@api_view(['POST'])
def home(request, *args, **kwargs):
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
instance = serializer.save()
# instance = serializer.save(commit=False)
# instance.content = 'My Test content'
print(instance)
return Response(serializer.data)
Пояснение:
- Теперь функция может передавать данные в БД.
- Выглядит также, если бы мы сохраняли какую-то валидную форму в нашей функции.
- Где оставил закомментировано, это возможность присваивать значения при публикации.
Давайте попробуем. Для отправки запросов я использую программу INSOMNIA. Скачать ее можно тут: The API Design Platform and API Client - Insomnia
В программе я ввел новые данные для отправки, и ссылку на запрос:

Нажимаем отправить и получаем результат и статус запроса: 200 OK

Давайте убедимся, что статья добавилась в админке:

Отлично. Статья и вправду добавилась. В следующем уроке мы рассмотрим CRUD запросы на основе классов. Они выглядят намного меньше, и запутаться с ними не так трудно.
Надеюсь у Вас все получилось! Вы большой молодец :3