Интеграция React приложения в Django проект

Часы
03.08.2024
Часы
01.02.2025
Часы
6 минут
Глазик
355
Сердечки
0
Соединённые точки
0
Соединённые точки
0
Соединённые точки
0

Вступление

В этой статье, я покажу тебе, как интегрировать React в Django проект. Идея такой интеграции заключается в том, чтобы дать Джанге отрендерить свои шаблоны, чтобы после этого наше Реакт приложение перехватило отрендеренную страницу и модифицировало её.
Если ты хочешь пропустить базовую установку и настройку, переходи сразу к установке Реакта. Так же ты можешь установить уже готовый базовый проект для этой главы. Если хочешь.

Создание Django проекта

Мы начнём с создания главной директории:
mkdir SearchResultParser
cd SearchResultParser
Теперь создадим и активируем виртуальное окружение, если для windows то:
python -m venv .venv
.venv\Scripts\Activate.ps1
Если для linux, то:
python -m venv .venv
source ./.venv/Scripts/activate
После активации окружения, установим сам django и начнём новый проект. Назовём его Website.
pip install django
django-admin startproject Website
cd Website
Если всё сделано верно, мы сможем запустить наш базовый проект и убедиться в этом. Вот так:
python ./manage.py runserver

Создание Backend приложения

Теперь нужно установить парочку новых питоновских пакета, для корректной работы с API нашего сайта. Вот эти пакеты
  1. django-cors-headers: для активации так называемого Cross-Origin Resource Sharing (CORS) для общения React приложения и Django API.
  2. djangorestframework: это Django приложение, которое позволит нам с лёгкостью построить АПИ для нашего сайта.
Установим их и создадим наше первое приложение:
pip install djangorestframework django-cors-headers
python ./manage.py startapp Backend
Отредактируй settings.py файл в своём любимом редакторе. В моём случае это будет NeoVim. Теперь подключим приложение Backend к нашему проекту.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'rest_framework',
'Backend.apps.BackendConfig',
]

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
]

CORS_ORIGIN_WHITELIST = [
'http://localhost:3000'
]
Создай файл urls.py, для linux:
touch Backend/urls.py
Для windows:
Get-Item Backend/urls.py
Вставь следующий контент в urls.py . Он находится в папке Website:
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from Backend import views

router = routers.DefaultRouter()
router.register(r'results', views.BackendModelView, 'result')

urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
]
Мы импортировали роутеры для REST фреймворка и представления из ранее созданного приложения Backend, а потом подключили. А сейчас создадим временную модель, В файле Backend/models.py вставь:
from django.db import models

class BackendModel(models.Model):
title = models.CharField(max_length=120)
description = models.TextField()

def _str_(self):
return self.title
Подключим нашу временную модель к админке django, в файле Backend/admin.py вставь:
from django.contrib import admin
from .models import BackendModel

class BackendModelAdmin(admin.ModelAdmin):
list_display = ('title', 'description')

admin.site.register(BackendModel, BackendModelAdmin)
Чтобы REST фреймворк работал, ему нужен сериализатор для модели. Он конвертирует django модели в JSON файлы и в таком виде отправляет через запросы. Открой(Создай) файл Backend/serializers.py и вставь следующее содержимое:
from rest_framework import serializers
from .models import BackendModel

class BackendModelSerializer(serializers.ModelSerializer):
class Meta:
model = BackendModel
fields = ('id', 'title', 'description')
Последнее, что нам осталось сделать, так это сделать класс-представление для нашей временной модели, BackendModel. Открой файл Backend/views.py и добавь следующий код:
from django.shortcuts import render
from rest_framework import viewsets
from .serializers import BackendModelSerializer
from .models import BackendModel

class BackendModelView(viewsets.ModelViewSet):
serializer_class = BackendModelSerializer
queryset = BackendModel.objects.all()
Создаём миграции, применяем их, а так же создадим суперпользователя. Он в будущем пригодится:
python ./manage.py makemigrations
python ./manage.py migrate
python ./manage.py createsuperuser

Создание Frontend приложения

Настало время для создания Frontend приложения. Это приложение и будет содержать наше react приложение. Но сначала нужно создать django приложение, настроить и подключить его. Всё, как всегда:
python ./manage.py startapp Frontend
В файле settings.py подключим его:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'rest_framework',
'Backend.apps.BackendConfig',
'Frontend.apps.FrontendConfig',
]

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
]
А в файле Frontend/urls.py подключим представления:
from django.urls import path
from .views import main

urlpatterns = [
path('', main, name='main')
]
Которое создадим в Frontend/views.py:
from django.shortcuts import render

def main(request):
return render(request, 'Frontend/app.html')
Теперь создадим шаблон по указанному адресу. И директории тоже:
mkdir Frontend/templates
mkdir Frontend/templates/Frontend
Get-Item Frontend/templates/Frontend/app.html
Теперь подключим созданный ранее urls.py файл в Website/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from Backend import views

router = routers.DefaultRouter()
router.register(r'results', views.BackendModelView, 'result')

urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
path('', include('Frontend.urls')),
]

Установка и настройка React

Настало время установить React. Не переживай, это просто если ты знаешь что нужно устанавливать) Зайдём в Frontend приложение и создадим несколько статических директорий там:
cd Frontend
mkdir static
mkdir static/js #Для скриптов
mkdir static/img #Для картинок
mkdir static/css # Для стилей
mkdir src
mkdir src/components # Для ReactJS компонентов
Почему я не добавил Frontend директорию в static, как это обычно делают? Дело в том, что наш сайт может содержать несколько приложений и чтобы у все их был доступ к реакту мы не создаём данную директорию.
На данном шаге настройка и подготовка Frontend приложения Django завершена, перейдём к установке необходимых пакетов для react. Я надеюсь npm уже установлен?
npm init -y
Устанавливай пакеты один за другим. Нам необходимы следующие пакеты:
  1. webpack для объединения всего нашего JS кода
  2. babel для перевода наших JS и CSS файлов в специфичный для каждого отдельного браузера.
  3. react для разработки фронтенда
npm i webpack webpack-cli --save-dev ;
npm i @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev ;
npm i react react-dom --save-dev ;
npm install @babel/plugin-proposal-class-properties ;
npm install react-router-dom;
Не пытайся объединить все команды из оболочки в одну. Node.js не сможет с этим справиться одновременно.
После установки необходимых пакетов нужно настроить Babel. Создай файл настройки; назови его babel.config.json. И вставь следующий конфигурационный код:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "10"
}
}
],
"@babel/preset-react"
],
"plugins": ["@babel/plugin-proposal-class-properties"]
}
Теперь настроим webpack пакет, но сначала создадим настроечный файл. Назови этот файл webpack.config.js. И вставь следующий конфигурационный код:
const path = require("path");
const webpack = require("webpack");

module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./static/js"),
filename: "[name].js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
],
},
optimization: {
minimize: true,
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
// This has effect on the react lib size
NODE_ENV: JSON.stringify("production"),
},
}),
],
};
Теперь, немного пошаманим в файле package.json. Если быть конкретней, то мы добавим два скрипта для управления работой npm:
{
"name": "frontend",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "webpack --mode development --watch",
"prod": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/preset-react": "^7.24.7",
"babel-loader": "^9.1.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"webpack": "^5.93.0",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.18.6",
"react-router-dom": "^6.25.1"
}
}

Создавая первый react компонент

После того как мы всё настроили давай напишем немного react кода. В папке Frontend/src, создай файл index.js, а в папке Frontend/src/components, создай файл App.js. Теперь вставим временный код в созданный файл src/components/App.js:
import React from 'react';
import { createRoot } from 'react-dom/client';

const App = () => {
return <h1>Rendered by Django, cooked by React</h1>;
};

export default App;

const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App />);
Подключим созданный компонент в src/index.js:
import App from './components/App';
И в конце концов, вставим код для нашего шаблонного файла templates/Frontend/app.html:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React with Django</title>
</head>
<body>
<div id="app"></div>
<script src="{% static 'js/main.js' %}"></script>
</body>
</html>
Теперь всё настроено. Давай проверим работает ли? Запустим сервер django и сервер webpack через ранее созданный скрипт:
python ./manage.py runserver
npm run dev
Если всё сделано правильно, ты увидишь что-то вроде этого
Пример простого проекта на django и react

Заключение

Всё начинается с того что Django отрисовывает шаблон. После чего React перехватывает эту страницу, находит элемент по id “app” и отрисовывает наш h1 тег. Теперь мы имеем готовый фулстек приложение готовое чтобы его доделали (❁´◡`❁)
Если ты пропустил всё что было выше и хочешь просто готовое-к-использованию решение, то ты можешь скачать его здесь. Это архив с настроенной структурой директорий и готовыми зависимостями. Всё что тебе остаётся сделать, так это скачать, создать виртуальное окружение, установить все необходимые python и npm пакеты.
В следующей статье, я покажу базовую раскладку и интерфейс для нашего проекта. И как её сделать при помощи реакта.

Общие ошибки, баги и недоразумения

Неправильная структура проекта

Ошибка: Неправильная организация каталога проекта, что приводит к путанице и трудностям в управлении кодовыми базами React и Django.
Решение: Поддерживайте четкую и логичную структуру каталогов. Храните код для фронтенда и бэкенда в отдельных каталогах.

Игнорирование проблем CORS

Ошибка: Игнорирование настроек Cross-Origin Resource Sharing (CORS), что может привести к блокировке запросов.
Решение: Настройте проект Django для обработки CORS. Используйте django-cors-headers, чтобы разрешить определенные источники запросов.

Непоследовательная конфигурация среды

Ошибка: Наличие конфликтующих или непоследовательных конфигураций среды, что приводит к проблемам в сборках разработки и производства.
Решение: Убедитесь, что переменные среды определены последовательно. Используйте такие инструменты, как dotenv , для управления переменными среды как в React, так и в Django.

Неправильная обработка статических файлов

Ошибка: Неправильная настройка обработки статических файлов, что может привести к проблемам при обслуживании ресурсов React в Django.
Решение: Правильно настройте Django для обслуживания статических файлов и убедитесь, что ресурсы React размещены в каталоге, который Django может обслуживать

Игнорирование конфликтов маршрутизации на стороне клиента

Ошибка: Игнорирование потенциальных конфликтов между механизмами маршрутизации Django и React Router, что приводит к неработоспособным ссылкам или неправильной маршрутизации.
Решение: Делегируйте клиентскую маршрутизацию React Router и убедитесь, что Django обслуживает приложение React для всех соответствующих маршрутов.

Комментарии

(0)

captcha
Отправить
Сейчас тут пусто. Буть первым (o゚v゚)ノ

Другое