Разработка приложений на React + Django

Разработка приложений на React + Django

Простая настройка окружения разработчика для создания приложений с использованием React и Django через проксирование запросов, без настройки CORS.

Современный пользовательский интерфейс в веб-приложениях часто делают на таких фреймворках, как React. Серверная же часть может использовать различные технологии. В данной статье рассмотрим наиболее простой способ подружить React и Django.

Создаем папку для будущего приложения и переходим в нее. Далее создаем виртуальное окружение и устанавливаем необходимые пакеты.

shell

python3 -m venv venv
source venv/bin/activate    # для Linux/Mac
venv\Scripts\activate    # для Windows
pip install django django-rest-framework

Создаем новый проект Django, например, назовем backend

shell

django-admin startproject backend
cd backend

и новое приложение, которое назовем, например, myapi

shell

python manage.py startapp myapi
python manage.py migrate
python manage.py createsuperuser --username $USER --email admin@example.com

Сохраняем установленные библиотеки в файл requirements.txt и поддерживаем его в актуальном состоянии. В дальнейшем, он нам понадобится для развертывания приложения на компьютере другого разработчика или продакшн сервере.

shell

pip freeze > requirements.txt

Теперь можно запустить ваше приложение

shell

python manage.py runserver

На этом этапе у вас уже должна работать админка http://127.0.0.1:8000/admin/

Добавим в файл настроек backend/settings.py наши модули

python

INSTALLED_APPS = [
    ...
    'rest_framework',
    'myapi',
]

Так же, начиная с Django 4.0, мы должны указать список доверенных источников для небезопасных запросов (например, POST). Еще зададим значения STATIC_ROOT и STATIC_URL, они понадобятся на этапе развертывания проекта.

python

CSRF_TRUSTED_ORIGINS = ['http://localhost:3000', 'http://127.0.0.1:3000']
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'

Создаем простой обработчик, для этого напишем его в файле myapi/views.py. Обработчик можно писать на классах или в виде отдельных функций. Рассмотрим оба варианта.

python

from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import generics

@api_view(['GET'])
def Hello(request):
    if request.method == 'GET':
        data = {'message': 'Hello world!'}
        return Response(data)

class Bye(generics.RetrieveAPIView):
    def get(self, request, *args, **kwargs):
        data = {'message': 'Bye world!'}
        return Response(data)

Далее нужно настроить маршрутизацию адресов. Для этого создаем в нашем модуле файл маршрутизации myapi/urls.py и прописываем в него все вызовы API функций.

python

from django.urls import path
from myapi import views

urlpatterns = [
    path('hello/', views.Hello),
    path('bye/', views.Bye.as_view()),
]

Далее открываем основной файл маршрутизации приложения backend/urls.py и добавляем в него пути к нашим модулям

python

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('myapi.urls')),
    # Можно подключать несколько модулей с непересекающимися подпутями на один путь
    # path('api/', include('another.urls')),
]

Если все написали правильно, то теперь можно посмотреть как работают наши API запросы http://127.0.0.1:8000/api/hello/ и http://127.0.0.1:8000/api/bye/.

Далее нужно выбрать вариант установки: Стандартный или с Vite

Устанавливаем React. Для этого переходим в корневой каталог нашего проекта и запускаем установку. Для примера будем использовать TypeScript.

shell

cd ..
npx create-react-app frontend --template typescript

Поскольку Django сервер и React сервер – это два разных сервера, которые друг про друга ничего не знают, будем проксировать все запросы к API из React сервера в Django. Это проще и удобнее, чем настраивать кросс-доменные запросы CORS. Редактируем файл frontend/package.json и добавляем туда строку, указывающую использование прокси.

json

{
    "proxy": "http://localhost:8000",
  ...
}

Теперь все внешние запросы будут перенаправляться через этот прокси в наше Django приложение. Это удобно тем, что данная настройка влияет только на сервер разработки и никак не влияет на конечное приложение, развернутое в продакшене. Так же, на стороне Django сервера не нужно вносить никаких изменений. Подробнее можно почитать в официальной документации.

Переходим в каталог frontend и запускаем сервер разработки

shell

cd frontend
npm start

Сервер должен успешно запуститься и откроется страница приложения http://localhost:3000/

Если мы хотим использовать более современную систему разработки и сборки проекта, можем установить React с системой Vite. Также будем использовать TypeScript. Для установки обычного JavaScript используйте шаблон react.

shell

cd ..
npm create vite@latest frontend -- --template react-ts

Настроим Vite для отправки запросов к нашему API через Proxy. Редактируем frontend/vite.config.ts

ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [react()],
    server: {
        port: 3000,
        proxy: {
            '/api': {
                target: 'http://127.0.0.1:8000',
                changeOrigin: true,
                secure: false,
                ws: true,
            }
        },
    },
})

Запустим среду разработки

shell

cd frontend
npm install
npm run dev

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

shell

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

И настроим, поправив файл tailwind.config.js

js

/** @type {import('tailwindcss').Config} */
export default {
    content: [
        "./index.html",
        "./src/**/*.{js,ts,jsx,tsx}",
    ],
    theme: {
        extend: {},
    },
    plugins: [],
}

Далее подключим к нашим стилям src/index.css библиотеку Tailwind CSS. Для этого очищаем все содержимое этого файла, оставшееся от шаблонного примера, и записываем следующее:

css

@tailwind base;
@tailwind components;
@tailwind utilities;

Сделаем простенький API запрос. Открываем src/App.tsx и заменяем старое содержимое на это:

typescript

import { useState } from 'react';

function App() {
    const [url, setUrl] = useState('hello');
    const [message, setMessage] = useState('Wait...');
    const handleClick = () => {
        fetch('/api/'+url)
            .then(response => response.json())
            .then(json => {
                setMessage(json['message']);
                if(url==='hello')
                    setUrl('bye');
                else
                    setUrl('hello');
            })
            .catch(error => console.error(error));
    };

    return (
        <div  className="mx-auto max-w-3xl px-4 sm:px-6 xl:max-w-5xl xl:px-0">
            <button
                className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 mt-4 rounded"
                onClick={handleClick}>
                <pre>{message}</pre></button>
        </div>
    );
}
export default App;

Если у вас при нажатии на кнопку надпись не меняется, убедитесь, что Django сервер тоже запущен в другом окне.

В итоге мы получили простое приложение с интерфейсом на React + Tailwind CSS, состоящее из одной кнопки и обработчиком API запросов на Django.

В следующей статье мы настроим продакшн сервер с нашим приложением в Docker контейнерах и SSL сертификатом Развертывание React + Django для публичного доступа.

Похожее