Integration a React app into Django project

Intoduction

In this article, I will show you how to integrate a React application into a Django project. The idea is that Django renders its templates, and React modifies them as needed
If you want to skip the basic setup and move on to the React integration part.
Also you can download a ready-made project for it.

Create a Django project

We will start by creating a root directory for our project.
mkdir SearchResultParser
cd SearchResultParser    
Now, create and activate a virtual environment.
Linux
Windows
python -m venv .venv
source ./.venv/Scripts/activate
python -m venv .venv
.venv\Scripts\Activate.ps1    
After activating a virtual environment, we have to install django package and start a new project. Let’s call it a Website.
pip install django
django-admin startproject Website
cd Website
If everything is done right, we will successfully launch a project. Just like that:
./manage.py runserver

Create a Backend app

Now, we need to install a couple of new Python packages to configure our Backend app.
django-cors-headers: for enabling so-called Cross-Origin Resource Sharing (CORS) for communication between React app and Django API.
djangorestframework: an Django app that allows us to build an API for further use.
pip install djangorestframework django-cors-headers
Create a Backend app
./manage.py startapp Backend
Edit the settings.py file using your favorite text editor. In my case, it is NeoVim. We will link the newly created app and those that we installed earlier.
nvim Backend/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',
]

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',
]
Add this at the end of settings.py file:
CORS_ORIGIN_WHITELIST = [
    'http://localhost:3000'
]
For now, create a urls.py file:
Linux
Windows
touch Backend/urls.py           
Get-Item Backend/urls.py           
Paste the next content in the urls.py file in the Website folder by this:
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)),
]
Here we imported routers for rest_framework and views from our Backend app and then included them into urlpatterns. The next thing we will do is to create a placeholder model for now.
nvim 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
And link our model with the default Django admin app.
nvim 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)
To work, the rest framework needs to have a serializer class. What he does is convert Django models into JSON files for us.
Linux
Windows
touch Backend/serializers.py           
Get-Item Backend/serializers.py           
nvim Backend/serializers.py
from rest_framework import serializers
from .models import BackendModel

class BackendModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = BackendModel
fields = ('id', 'title', 'description')
The last thing we need to do is create a specific view class for BackendModel.
nvim 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()
At the end, create all migrations and apply them.
./manage.py makemigrations
./manage.py migrate
Also create a super user to gain access to the database.
./manage.py createsuperuser

Create a Frontend app

It is time for the Frontend app. This app is going to contain our React app. But first, we need to create, link, and prepare this app.
./manage.py startapp Frontend
nvim Website/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',
]
Create an urls.py file for the Frontend app and paste the next content.
Linux
Windows
touch Frontend/urls.py           
Get-Item Frontend/urls.py           
nvim Frontend/urls.py
from django.urls import path
from .views import main

urlpatterns = [
    path('', main, name='main')
]
The same, we need to create the main function. It is a placeholder; in the future, this function is going to be deleted.
nvim Frontend/views.py
from django.shortcuts import render

def main(request):
    return render(request, 'Frontend/app.html')
To render something, we need to create an HTML file.Β 
mkdir Frontend/templates
mkdir Frontend/templates/Frontend
Linux
Windows
touch Frontend/templates/Frontend/app.html           
Get-Item Frontend/templates/Frontend/app.html           
And include the created earlier urls.py file in the Frontend directory in the main urls.py file in the Website directory.
nvim 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 installation

Now it is time for React installation. It is relatively easy if you know what to install ;). Go to the Frontend directory and create a static directory:
cd Frontend
mkdir static
To store all js bundles
mkdir static/js
To store all images
mkdir static/img
To store all css files
mkdir static/css
To store all react components
mkdir src
mkdir src/components
Chevron Why don't we add a Frontend folder to the static folder like usual? We might have to create another Django app, and since we want to use React throughout the site, we haven't created a Frontend folder.
At this step, the Frontend app is ready, and the last thing to do is to create and configure the React app.
npm init -y
Install initial packages, one by one:
webpack to bundle all of our JS code
babel for translating all of our JS and CSS code into friendly types for each browser.
react for developing all of our frontend parts of the website
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;
Chevron Do not try to combine all of the above shell’s commands into a single one. Node.js could not handle all of it at once. After installing the required packages, we need to configure Babel.
We’re still in the Frontend directory. Create a config file:
Linux
Windows
touch babel.config.json           
Get-Item babel.config.json           
And then paste it:
{
Β  Β  "presets": [
Β  Β  Β  Β  [
Β  Β  Β  Β  Β  Β  "@babel/preset-env",
Β  Β  Β  Β  Β  Β  {
Β  Β  Β  Β  Β  Β  Β  Β  "targets": {
Β  Β  Β  Β  Β  Β  Β  Β  Β  Β  "node": "10"
Β  Β  Β  Β  Β  Β  Β  Β  }
Β  Β  Β  Β  Β  Β  }
Β  Β  Β  Β  ],
Β  Β  Β  Β  "@babel/preset-react"
Β  Β  ],
Β  Β  "plugins": ["@babel/plugin-proposal-class-properties"]
}
Configure a webpack packet, but first do not forget to create a config file:
Linux
Windows
touch webpack.config.js           
Get-Item 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"),
Β  Β  Β  },
Β  Β  }),
Β  ],
};
Configuring package.json file. Paste this into scripts list:
{
Β  "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"
Β  }
}

Creating first react component

After everything is set up, let’s write some React code. In a Frontend/src folder, create an index.js, and in Frontend/src/components, create an App.js file.
Linux
Windows
touch src/index.js;
touch src/components/App.js;           
Get-Item src/index.js
Get-Item src/components/App.js           
Then paste this example code into 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 />);
We need to include the App component in index.js. Paste this:
import App from './components/App';
At the end, we need to paste this example code into the app.html file. His location is Frontend/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>
Everything is set up. Now, let’s test it. Firstly, run django server:
./manage.py runserver
Secondly start React app
npm run dev
If you did all right, you will see something like this.
An example of simple project on djanog and react

Conclusion

All begins with Django’s rendered template. After this, React is going to find a div by id β€œapp” and render our h1 tag. Now we have a full-stack app that is ready to be developed.
If you skipped all of the above and just want a ready-to-use solution, here it is. An archive with preconfigured folder structure and precalculated dependencies. All you need to do is set up a virtual environment (install all required Python packages) for the downloaded folder and install the required NPM packages in the Frontend app.
In the next article, I will show you the basic layout for a website and what it is going to look like.

Common errors, bugs and mistakes


heart 2
3 connected dots 1