Application development using React + Django

Modern user interfaces in web applications usually built using frameworks such as React. The server part can use various technologies. In this article we will look at the easiest way to make friends with React and Django.

Create a folder for the future application and go to it. Next, we create a virtual environment and install the necessary packages.

shell

python3 -m venv venv
source venv/bin/activate    # for Linux/Mac
venv\Scripts\activate    # for Windows
pip install -U pip setuptools django django-rest-framework

Create a new Django project, for example, call it backend

shell

django-admin startproject backend
cd backend

and a new application, which we will call, for example, myapi

shell

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

Now you can launch your application

shell

python manage.py runserver

At this stage, your admin panel should already be working http://127.0.0.1:8000/admin/

Let’s add our modules to the settings file backend/settings.py

python

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

Starting from Django 4.0, you have to include a list of trusted origins for unsafe requests (e.g. POST)

python

CSRF_TRUSTED_ORIGINS = ['http://localhost:3000', 'http://127.0.0.1:3000']

Let’s create a simple handler; to do this, we’ll write it in the file myapi/views.py. The handler can be written using classes or as separate functions. Let’s consider both options.

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)

Next you need to configure URL routing. To do this, we create a routing file myapi/urls.py in our module and write all the API function paths into it.

python

from django.urls import path
from myapi import views

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

Next, open the main application routing file backend/urls.py and add the paths to our modules to it.

python

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('myapi.urls')),
    # You can place several modules with non-overlapping subpaths on one path
    # path('api/', include('another.urls')),
]

If everything was written correctly, now you can see how our API requests http://127.0.0.1:8000/api/hello/ and http://127.0.0.1:8000/api/bye/ work.

You need to install React. To do this, go to the root directory of our project and start the installation. For example, we will use TypeScript.

shell

npx create-react-app frontend --template typescript

Since the Django server and the React server are two different servers that do not know about each other, we will proxy all requests to the API from the React server to Django. This is easier and more convenient than setting up cross-domain requests CORS. We edit the frontend/package.json file and add a line there indicating the use of a proxy.

json

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

Now all external requests will be redirected through this proxy to our Django application. This is convenient because this setting only affects the development server and does not in any way affect the final application deployed in production. Also, there is no need to make any changes on the Django server side. You can read more in the official documentation.

Go to the frontend directory and start the development server

shell

cd frontend
npm start

The server should start successfully and the application page http://localhost:3000/ will open.

Let’s make a simple API request. Open src/App.tsx and replace the old content with this:

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>
      <button onClick={handleClick}><pre>{message}</pre></button>
    </div>
  );
}
export default App;

A result we received a simple application with a React interface consisting with button and an API request handler in Django.