Учебник для начинающих

В этом руководстве мы узнаем, как создать приложение CRUD Todo с фреймворком Django REST для внутреннего интерфейса, React и Redux для внешнего интерфейса.

В конце этого урока у нас будет приложение, которое выглядит так:

Оглавление

  • Настройка Django
  • Настройка React
  • Получение данных из API и отображение списка
  • Создание формы и добавление нового Todo
  • Создание заголовка
  • Удаление Todos
  • Редактирование Todos

Настройка Django

Создание виртуальной среды с Pipenv

Сначала мы создадим папку для проекта и перейдем в нее:

$ mkdir django-react-todo
$ cd django-react-todo

Давайте создадим виртуальную среду, выполнив эту команду:

$ pipenv --python 3

Если у вас еще не установлен Pipenv, установите его, выполнив следующую команду:

$ pip install pipenv

Установим нужные нам пакеты:

$ pipenv install django djangorestframework

Создание нового проекта и некоторых приложений

В этом руководстве мы создадим проект под названием «todocrud». Мы можем опустить дополнительную папку, которая создается автоматически, если добавить точку в конец команды и запустить:

$ django-admin startproject todocrud .

Далее мы создадим два приложения. Один для бэкэнда, другой для фронтенда:

$ python manage.py startapp todos
$ python manage.py startapp frontend

Мы откроем файл settings.py в каталоге проекта и настроим использование созданных нами приложений и инфраструктуры Django REST:

Мы можем указать выходной формат даты и времени, включив DATETIME_FORMAT в словарь конфигурации с именем REST_FRAMEWORK.

Применим миграции и запустим сервер разработки:

$ python manage.py migrate
$ python manage.py runserver

Посетите http://127.0.0.1:8000/ в своем браузере. Если вы видите страницу взлетающей ракеты, значит, она сработала!

Написание модулей backend

Сначала мы создадим простую модель. Откройте файл models.py и напишите следующий код:

Затем мы создадим простой API на основе модели с использованием инфраструктуры REST. Давайте создадим новую папку с именем api и создадим в ней новые файлы __init__.py, serializers.py, views.py и urls.py:

todos/
  api/
    __init__.py
    serializers.py
    urls.py
    views.py

Поскольку api - это модуль, нам нужно включить __init__.py файл.

Давайте определим представление API в файле serializers.py:

Класс ModelSerializer создаст поля, соответствующие полям модели.

Затем мы определим поведение представления в файле api/views.py:

Наконец, мы напишем конфигурацию URL, используя Routers:

Мы используем три аргумента метода register(), но третий аргумент не требуется.

Написание модулей внешнего интерфейса

В интерфейсе все, что нам нужно сделать, это написать простые представления и шаблоны URL.

Откройте файл frontend/views.py и создайте два представления:

Мы создадим файл frontend/index.html позже. Не беспокойся об этом сейчас.

Добавьте новый urls.py файл в тот же каталог и создайте URL conf:

Как вы можете видеть выше, представление index предназначено для страницы индекса, а TodoDetailView вызывается, когда мы запрашиваем конкретный объект.

Подключите URL-адреса

Мы включим URL-адреса внешнего и внутреннего интерфейса в URLconf проекта:

Хотя путь к сайту Django admin оставлен, мы не собираемся использовать его в этом руководстве.

В заключительной части этой главы мы создадим новый файл миграции и внесем изменения в наши базы данных, выполнив следующие команды:

$ python manage.py makemigrations
$ python manage.py migrate

Настройка React

Создание каталогов

Прежде всего, создадим все нужные нам каталоги:

$ mkdir -p ./frontend/src/{components,actions,reducers}
$ mkdir -p ./frontend/{static,templates}/frontend

Приведенная выше команда должна создать каталоги следующим образом:

frontend/
  src/
    actions/
    components/
    reducers/
  static/
    frontend/
  templates/
    frontend/

Установка пакетов

Нам нужно создать файл package.json, выполнив следующую команду перед установкой пакетов:

$ npm init -y

Для использования npm необходимо установить Node.js.

Затем давайте установим все используемые нами пакеты с помощью команды npm:

$ npm i -D webpack webpack-cli
$ npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties
$ npm i react react-dom react-router-dom
$ npm i redux react-redux redux-thunk redux-devtools-extension
$ npm i redux-form
$ npm i axios
$ npm i lodash

Создание файлов конфигурации

Добавьте файл с именем .babelrc в корневой каталог и настройте Babel:

Мы можем использовать Async / Await с Babel, написав, как указано выше.

Во-вторых, добавьте файл с именем webpack.config.js в тот же каталог и напишите конфигурацию для webpack:

Кроме того, нам нужно переписать свойство "scripts” файла package.json:

Были определены два новых скрипта. Мы можем запускать сценарии с npm run dev для разработки или npm run build для производства. При запуске этих сценариев webpack объединяет модули и выводит main.js файл.

Создание основных файлов

Давайте создадим три основных файла и отобразим первое слово.

Мы создадим файл с именем index.js, который будет вызываться первым при запуске приложения React:

Затем мы создадим файл с именем App.js, который является родительским компонентом:

Наконец, мы создадим файл шаблона с именем index.html, который указан в файле views.py:

В этом руководстве мы будем использовать Semantic UI как основу CSS.

Поместите оболочку для рендеринга компонента App и связанного скрипта в тег <body>.

Проверка дисплея

Посмотрим, правильно ли он отображается.

Откройте другой терминал и запустите скрипт:

$ npm run dev

Файл main.js должен быть создан в каталоге static/frontend.

Затем запустите сервер разработки и зайдите на http://127.0.0.1:8000/:

$ python manage.py runserver

Если отображается слово «ToDoCRUD», пока все идет хорошо :)

Получение данных из API и отображение списка

Пора использовать Redux. Мы создадим Действия, Редукторы и Магазин.

Действия

Заранее определим все свойства типа. Добавьте новый файл с именем types.js в каталог src/actions:

Чтобы создать действия, нам нужно определить Создатели действий. Добавьте новый файл с именем todos.js в каталог src/actions:

Редукторы

Редукторы определяют, как состояние приложения изменяется в ответ на действия, отправленные в магазин.

В этом роль редукторов. Добавьте новый файл с именем todos.js в каталог src/reducers и напишите дочерний редуктор:

Lodash - это служебная библиотека JavaScript. Это не является обязательным требованием, но может сократить время разработки и уменьшить размер кодовой базы.

Давайте создадим родительский редуктор, чтобы собрать каждый дочерний редуктор с помощью combineReducers(). Добавьте новый файл с именем index.js в каталог src/reducers:

Чтобы использовать redux-form, нам нужно включить его редуктор в функцию combineReducers.

Магазин

Магазин - это объект для хранения состояния нашего приложения. Кроме того, мы будем использовать рекомендованное промежуточное ПО Redux Thunk для написания асинхронной логики, которая взаимодействует с хранилищем. Давайте создадим новый файл с именем store.js в каталоге src:

Использование Redux DevTools необязательно, но очень полезно, поскольку позволяет визуализировать изменения состояния Redux. Я не буду здесь рассказывать, как его использовать, но настоятельно рекомендуется.

Компоненты

Сначала создайте новую папку с именем todos в каталоге components. А затем добавьте новый файл с именем TodoList.js в созданную нами папку:

Мы используем список семантического пользовательского интерфейса для украшения списка.

Функция connect() подключает этот компонент к магазину. Он принимает mapStateToProps в качестве первого аргумента, а Создатели действий - в качестве второго аргумента. Мы сможем использовать состояние магазина как свойства, указав mapStateToProps.

Мы создадим новый файл с именем Dashboard.js в том же каталоге. Это просто контейнер для TodoList и форма, которую мы создадим в следующей главе:

Откройте файл App.js и обновите его следующим образом:

Provider делает хранилище доступным для вложенного в него компонента.

Проверка дисплея

Сначала зайдите на http://127.0.0.1:8000/api/todos/ и создайте несколько объектов. Затем зайдите на http://127.0.0.1:8000/.

Вы должны увидеть простой список созданных вами объектов. Это сработало?

Создание формы и добавление нового Todo

Действия

Откройте файл actions/todos.js и добавьте новый создатель действий:

Отправка reset('formName') очищает нашу форму после успешной отправки. Мы укажем имя формы позже в компоненте Форма.

Редукторы

Откройте файл reducers/todos.js и добавьте новое действие в редуктор:

Компоненты

Давайте создадим компонент формы. Мы создадим форму отдельно как компонент многократного использования, чтобы ее также можно было использовать для редактирования. Создайте новый файл с именем TodoForm.js в каталоге components/todos:

Учебник будет длинным, поэтому я опущу, как использовать Redux Form. Чтобы понять, как работает Redux Form, неплохо попробовать настроить вашу форму, ссылаясь на документацию.

'todoForm' - это имя этой формы. Это то, что мы использовали в создателе действий addTodo.

Когда мы щелкаем текстовое поле и затем удаляем фокус, отображается ошибка проверки, поэтому укажите touchOnBlur: false, чтобы отключить ее.

Затем давайте создадим компонент для добавления новых задач. Создайте новый файл с именем TodoCreate.js в каталоге components/todos:

Все, что нам нужно сделать, это отрендерить TodoForm. Установив destroyOnUnmount на false, мы можем отключить автоматическое уничтожение формы Redux Form в хранилище Redux при размонтировании компонента. Он предназначен для отображения состояния формы в форме редактирования.

Если нам не нужно указывать mapStateToProps функцию, установите null на connect().

Давайте посмотрим и протестируем форму. Откройте файл Dashboard.js и обновите его следующим образом:

Создание заголовка

Сделаем перерыв и создадим заголовок. Создайте новую папку с именем layout, а затем добавьте в нее новое имя файла Header.js:

Откройте файл App.js и вложите компонент Header:

В этом уроке заголовок - это просто украшение.

Удаление Todos

Сначала мы создадим объект history с помощью пакета history. Мы можем использовать его для изменения текущего местоположения. Создайте новый файл с именем history.js в каталоге frontend/src и напишите приведенный ниже код:

Действия

Откройте файл actions/todos.js и добавьте два новых средства создания действий:

Мы создали getTodo, чтобы получить конкретный объект, и deleteTodo, чтобы удалить объект.

Позже мы создадим модальное окно для подтверждения удаления. Метод history.push('/') автоматически переводит нас из модального окна на страницу индекса после удаления объекта.

Редукторы

Откройте файл reducers/todos.js и добавьте действия в редуктор:

Действие GET_TODO такое же, как действие ADD_TODO, поэтому нам нужно только установить case. Для действия DELETE_TODO снова используйте Lodash как ярлык.

Компоненты

Давайте создадим модальное окно, о котором я только что говорил. У нас получится вот так:

Создайте новый файл с именем Modal.js в каталоге components/layout и напишите следующее:

Чтобы отобразить компонент Modal вне иерархии DOM родительского компонента, создайте портал, используя createPortal(). Первый аргумент - это рендерируемый дочерний элемент, а второй аргумент - это элемент DOM для рендеринга.

Затем откройте файл index.html и добавьте контейнер для модального окна внутри тега <body>:

Затем мы создадим новый компонент TodoDelete.js в каталоге components/todos:

Код длинноват, но это не так уж и сложно. Определите вспомогательные функции, отображающие содержимое и кнопки действий в модальном окне. Затем передайте их как свойства в модальный компонент. onDismiss настроен на возврат к странице индекса при щелчке по тусклой части модального окна.

Мы можем получить данные из его собственных свойств, указав ownProps в качестве второго аргумента для mapStateToProps.

Давайте откроем TodoList.js файл и поставим кнопку удаления:

Наконец, нам нужно настроить маршрутизацию с помощью React Router. Откройте файл App.js и настройте следующим образом:

Причина использования Router вместо BrowserRouter объясняется в документе REACT TRAINING следующим образом:

Наиболее распространенный вариант использования низкоуровневого ‹Router› - это синхронизация пользовательской истории с библиотекой управления состоянием, такой как Redux или Mobx. Обратите внимание, что это не требуется для использования библиотек управления состоянием вместе с React Router, это только для глубокой интеграции.

Параметр exact, указанный в Route, возвращает маршрут, только если path точно соответствует текущему URL-адресу.

На этом завершаем эту главу. Попробуйте удалить некоторые объекты и посмотрите, работает ли это.

Редактирование Todos

Это последняя глава. Мы почти закончили, так что давайте продолжим!

Действия

Откройте файл actions/todos.js и добавьте новый создатель действий:

Редукторы

Откройте файл reducers/todos.js и добавьте действие в редуктор:

Компоненты

Создайте новый компонент TodoEdit.js в каталоге components/todos:

Укажите объект в initialValues. Мы можем получить только значение task с помощью _.pick функции Lodash. Кроме того, установите enableReinitialize в true, чтобы мы также могли получить значение при перезагрузке страницы. Передайте эти необязательные свойства в TodoForm.

Откройте файл TodoList.js и обновите <a className='header'>{todo.task}</a> следующим образом:

Давайте добавим новый компонент в App.js файл:

Наконец, давайте изменим текст кнопки в форме редактирования с «Добавить» на «Обновить». Откройте файл TodoForm.js и обновите его следующим образом:

Теперь щелкните любую задачу на странице индекса и попробуйте отредактировать:

Вы должны были изменить значение в форме.

На этом урок заканчивается. Исходный код этого приложения доступен на GitHub. Спасибо за чтение!

Следующий шаг