Автор перевода Полина Ревякина, копирайтер в Skillbox
В этом материале вы узнаете:
- как создать простое REST API на Django;
- как добавить React в проект Django;
- как соединить Django и React.
Подготовка
Вам понадобятся:
- базовое понимание Python и Django;
- базовое понимание JavaScript (и спецификации ECMAScript 2015) и React;
- установленный Node.js.
Создаём проект Django в виртуальном окружении Python
Создайте новую папку и перейдите в неё:
mkdir django-react && cd $_
Потом активируйте виртуальное окружение Python:
python3 -m venv venv source venv/bin/activate
Примечание все следующие команды нужно выполнять из папки django-react
и с активированным виртуальным окружением.
Установите зависимости Django и Django REST Framework:
pip install django djangorestframework
После установки создайте новый проект Django:
django-admin startproject django_react
Теперь сделаем простое API на Django для создания и хранения контактов.
Создаём приложение на Django
В каждом проекте Django может быть много приложений. Приложения можно делать переиспользуемыми: такими, что их можно добавить в менеджер пакетов Python и установить через него в другой проект, в котором нужно такое приложение.
Для создания нового приложения Django используется команда:
django-admin startapp app_name
где app_name
— название приложения.
В нашем случае команда будет выглядеть так:
django-admin startapp leads
Она создаст приложение leads
в папке django-react
. Теперь структура папок в проекте должна выглядеть так:
(venv) your@prompt:~/Code/django-react$ tree -d -L 1 . ├── django_react ├── leads └── venv
Теперь сделаем так, чтобы Django проект использовал новое приложение. Откройте файл django_react/settings.py
и добавьте приложение в INSTALLED_APPS
:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'leads.apps.LeadsConfig', # activate the new app ]
Создаём модель в базе данных с помощью Django
Модель — это объект, представляющий собой данные из таблицы. Почти каждый веб-фреймворк использует модели, и Django — не исключение.
Модель Django может иметь одно или больше полей. Каждое поле соответствует полю в таблице.
Мы собираемся хранить контакты, поэтому модель Lead
может состоять из этих полей:
- имя;
- email;
- сообщение.
(Можно добавлять и другие поля, например телефон). Добавим ещё поле с временем создания модели, потому что по умолчанию Django этого не делает.
Откроем leads/models.py
и опишем модель Lead
:
from django.db import models class Lead(models.Model): name = models.CharField(max_length=100) email = models.EmailField() message = models.CharField(max_length=300) created_at = models.DateTimeField(auto_now_add=True)
Примечаниеизучите документацию Django о полях. Когда придумываете структуру модели, выбирайте самые подходящие для вашего случая поля.
Создадим миграции командой:
python manage.py makemigrations leads
и применим их к базе данных:
python manage.py migrate
Займёмся тестированием
Вы могли подумать «А как же тестирование?».
Существует масса туториалов по Django, начинающихся примерно так:
class SomeModelModelTest(TestCase): def setUp(self): SomeModel.objects.create( name=fake.name(), email=fake.email(), phone=fake.phone_number(), message=fake.text(), source=fake.url() ) def test_save_model(self): saved_models = SomeModel.objects.count() self.assertEqual(saved_models, 2)
Не надо так. Нет никакого смысла ни в тестировании стандартной модели Django, ни в тестировании Django ORM. Что точно не нужно тестировать при создании приложения на Django:
- встроенный код Django (модели, представления);
- встроенные функции Python.
Не тестируйте то, что уже протестировано! Так что же тогда тестировать?
Добавили свой метод в модель Django — протестируйте его. Дополнили стандартное представление — протестируйте его. Но как узнать, что именно нужно протестировать?
Узнать это поможет библиотека coverage. Установите её:
pip install coverage
Теперь после каждого добавления или изменения кода запускайте coverage
:
coverage run --source='.' manage.py test
и создавайте отчёт:
coverage html
Вы увидите, что именно нужно протестировать. Если предпочитаете увидеть отчёт в командной строке, запустите команду:
coverage report
Сериализаторы Django
Сериализация — это конвертация объекта Python в другой формат. После сериализации можно сохранить объект в файл или послать его через сеть.
Почему сериализация необходима? Модель Django — это класс Python. Чтобы превратить её в данные в формате JSON, нужна сериализация.
Сериализаторы работают и в обратном направлении: они конвертируют JSON в объекты. Это позволяет:
- отображать модель Django в браузере с помощью конвертации в JSON;
- делать запросы CRUD (create – read – update – delete) к API в формате JSON.
Суммируя: сериализаторы в Django можно использовать для совершения операций с моделями Django через API.
Создайте новый файл leads/serializers.py
. Сериализатор LeadSerializer
содержит нашу модель и поля:
from rest_framework import serializers from .models import Lead class LeadSerializer(serializers.ModelSerializer): class Meta: model = Lead fields = ('id', 'name', 'email', 'message')
Созданный дочерний класс от класса serializers.ModelSerializer
. ModelSerializer
в Django похож на ModelForm
. Он подходит, когда нужно, чтобы сериализатор соответствовал модели.
Создаём представления
Если вы раньше работали с другими фреймворками, то можете удивиться, что в Django нет контроллеров.
Контроллеры содержат логику обработки запросов и возвращения ответов. В традиционной архитектуре MVC есть модель (Model), представление (View) и контроллер (Controller). Примеры MVC фреймворков: Rails (Ruby), Phoenix (Elixir), Laravel (PHP).
Django — это фреймворк MVT. MVT — это модель, представление и шаблон (Template). В Django есть много типов представлений: функции-представления, представления, основанные на классах, и обобщённые представления.
Используйте функции-представления только если изменение обобщенных представлений займет больше, чем написание представления заново.
Мы будем использовать обобщённые представления. Наше простое приложение будет:
- возвращать выборку моделей;
- создавать новые объекты в базе данных.
С помощью документации можно узнать, что есть представление для возвращения выборки и создания моделей: ListCreateAPIView
. Это представление содержит queryset
и serializer_class
.
queryset
— это выборка данных, которую приложение будет возвращать. В нашем случае — все модели Lead
. serializer_class
— класс сериализатора для модели.
from .models import Lead from .serializers import LeadSerializer from rest_framework import generics class LeadListCreate(generics.ListCreateAPIView): queryset = Lead.objects.all() serializer_class = LeadSerializer
С помощью трёх строк кода мы создали представление для обработки GET и POST запросов.
Чего ещё не хватает? Маршрутизации URL. Другими словами, нам нужно соединить URL и представления.
Настраиваем маршрутизацию url
Нам нужно сделать так, чтобы GET и POST запросы к api/lead/
обрабатывались представлением LeadListCreate
, которое будет возвращать и создавать модели.
Чтобы настроить маршрутизацию URL, отредактируйте файл django_react/urls.py
, добавив туда url приложения:
from django.urls import path, include urlpatterns = [ path('', include('leads.urls')), ]
Так мы указываем Django, что нужно использовать url, которые есть в приложения leads
.
Теперь создайте файл leads/urls.py
. В нём мы соединим представление LeadListCreate
и url api/lead/
:
from django.urls import path from . import views urlpatterns = [ path('api/lead/', views.LeadListCreate.as_view() ), ]
И наконец, включим rest_framework
в INSTALLED_APPS
. Откройте django_react/settings.py
и добавьте приложение в INSTALLED_APPS
:
# Application definition INSTALLED_APPS = [ # omitted for brevity 'leads.apps.LeadsConfig', 'rest_framework' ]
Запустим сервер Django:
python manage.py runserver
Перейдите по url http://127.0.0.1:8000/api/lead/ и вы увидите API:
Примечание в продакшене лучше отключить возможность просмотра API. Это можно сделать в конфигурации:
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', ) }
Соединяем Django и React
У многих разработчиков возникают вопросы по поводу того, как правильно соединить Django и React.
Должен ли роутер React взять на себя маршрутизацию? Нужно ли монтировать компоненты React в каждом шаблоне Django?
Ответ зависит от случая.
Есть следующие способы создания проекта на Django и React (они похожи почти для любого веб-фреймворка):
- React в собственном приложении Django для фронтенда. Загружаем один HTML шаблон и даём React управление фронтендом (сложность: средняя).
- Django REST как отдельное API + React как отдельное SPA (сложность: высокая, нужна будет авторизация по JWT).
- Смешанный вариант: мини-приложения React в шаблонах Django (сложность: просто, но сложно будет поддерживать).
Если вы только начали работать с Django REST и React, избегайте варианта 2. Вместо этого выберите 1 (React в собственном приложении Django для фронтенда), если:
- вы создаёте приложение, похожее на веб-сайт;
- в интерфейсе будет много пользовательских действий, используется AJAX;
- вас устраивает авторизация, основанная на сессиях;
- вас не очень волнуют вопросы SEO;
- вас устраивает роутер React.
Если будете держать React близко к Django, то будет проще с авторизацией. Можно будет использовать встроенную систему авторизации Django для регистрации и входа пользователей. Используйте старую добрую авторизацию с помощью сессий и не беспокойтесь о токенах и JWT.
Выберите вариант 3 (смешанный вариант: мини-приложения React в шаблонах Django), если:
- на сайте не нужно использовать много JavaScript;
- вам важно SEO и вы не можете использовать Node.js для рендеринга серверной части.
В данной статье мы будем использовать вариант 1.
Устанавливаем React и webpack
Создадим новое приложение Django для фронтенда:
django-admin startapp frontend
Вы увидите новую папку с названием frontend
в вашей структуре папок:
(venv) your@prompt:~/Code/django-react$ tree -d -L 1 . ├── django_react ├── frontend ├── leads └── venv
Подготовим папки для хранения компонентов React:
mkdir -p ./frontend/src/components
И статики:
mkdir -p ./frontend/{static,templates}/frontend
Дальше установим React, webpack и babel. Перейдите в папку frontend и создайте окружение:
cd ./frontend && npm init -y
Установите webpack и webpack CLI:
npm i webpack webpack-cli --save-dev
Откройте package.json
и запишите 2 скрипта для продакшна и для разработки:
"scripts": { "dev": "webpack --mode development ./src/index.js --output ./static/frontend/main.js", "build": "webpack --mode production ./src/index.js --output ./static/frontend/main.js" }
Сохраните и закройте файл.
Установим babel, чтобы код был совместим со старыми браузерами, которые не поддерживают последние стандарты JavaScript:
npm i @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev
Установим React:
npm i react react-dom --save-dev
Настроим Babel (по-прежнему находясь в папке frontend
):
{ "presets": [ "@babel/preset-env", "@babel/preset-react" ] }
Создадим файл webpack.config.js
для настройки загрузчика babel:
module.exports = { module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: "babel-loader" } } ] } };
Готовим приложение Django для фронтенда
Создадим представление в ./frontend/views.py
:
from django.shortcuts import render def index(request): return render(request, 'frontend/index.html')
Создадим шаблон в ./frontend/templates/frontend/index.html
: