Django REST Framework создание API: Урок: 3, сериализация данных на основе функций
avatar
7 | (offline)
❤️‍🔥Notehunter Developer
Добавлено:
Категория: Руководства «Django»
Комментариев: 0

В уроке 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

Теги записи: Django, Django REST Framework, API, DRF,
Комментарии к статье 0
Комментариев нет
Форма добавления комментария (необходима регистрация)