Django & React

React is a popular Javascript library for writing user interfaces. There are lots of websites on how to get started with React and only a few which talk about how to configure React & Django together. It is perfectly possible to keep the user interface and backend as separate projects but for smaller projects this is may not be applicable.

This is my first stab at writing down how to get them working together. Much of this is taken from Valentino Gagliardi’s blog. I’ve had to tweak some bits which seem to have changed since Valentino wrote his articles.

The Problem

Normally, when you want to create a React application you execute the command:

npx create-react-app my-react-app

But if you try and do this inside a Django application you’ll probably encounter the error:

The directory <> contains files that could conflict

One way to get around this is to put the React UI in a subdirectory of your Django application. Another way is to integrate it into your Django app manually.

Getting Started

I’m going to assume you’ve already got Django & npm installed.

As I’ve already written how to get started with Django so I’ll just list the commands to create the bare bones Django application:

$ mkdir PROJECT_NAME
$ cd PROJECT_NAME
$ virtualenv -p python3 virtualenv
$ source virtualenv/bin/activate
$ pip install django
$ django-admin startproject my_project .
$ django-admin startapp main

Then edit the file my_project/settings.py and in the section INSTALLED_APPS add the line:

'main',

Now we’ll start to add React.

First off, we need to create some directories for React in our application:

$ cd main
$ mkdir -p ./src/components
$ mkdir -p ./{static,templates}/frontend

Now we create a package.json file to tell npm what modules we want:

$ cat <<EOF >package.json
{
  "name": "frontend",
  "version": "1.0.0",
  "description": "My React Application",
  "main": "index.js",
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "John Smith",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.12.3",
    "@babel/preset-env": "^7.12.1",
    "@babel/preset-react": "^7.12.1",
    "babel-loader": "^8.1.0",
    "webpack": "^5.2.0",
    "webpack-cli": "^4.1.0"
  },
  "dependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-router": "^5.2.0"
  }
}
EOF

Next we need to create a configuration file for something called Babel. Babel allows Javascript programmers to ignore differences between browser Javascript engines.

$ cat <<EOF >babel.config.json
{
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react",
    ],
    "plugins": [
        "@babel/plugin-proposal-class-properties"
    ]
}
EOF

Up next is a Webpack configuration file. Webpack is used to package Javascript code.

$ cat <<EOF >webpack.config.js
const path = require('path');
 
module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'static/frontend'),
    filename: 'main.js'
  },
  module: {
    rules: [
      {
        loader: 'babel-loader',
        test: /\.js$/,
        exclude: /node_modules/,
      }
    ]
  }
};
EOF

Now we’ve created our configuration files, we can start to write some React.

$ cat <<EOF >src/index.js
import React from "react";
import ReactDOM from 'react-dom';
import App from "./components/App";
 
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('app')
);
EOF

$ cat <<EOF >src/components/App.js
import React, { Component } from "react";
import { render } from "react-dom";
 
export default class App extends Component {
  constructor(props) {
    super(props);
  }
 
  render() {
    return (
       <p>Hello World from React</p>
    );
  }
}
EOF

Now we can create a view to invoke React:

$ cat <<EOF >templates/frontend/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Django REST with React</title>
</head>
<body>
<div id="app">
    <!-- React will load here -->
</div>
{% load static %}
<script src="{% static "frontend/main.js" %}"></script>
</body>
</html>
EOF

$ cat <<EOF >>views.py
def index(request):
    return render(request, 'frontend/index.html')
EOF

Finally, we need to update urls.py in the Django Project directory to reference this view:

$ cd ../my_project
$ cat <<EOF >urls.py
from django.urls import path
 
urlpatterns = [
    path('', views.index),
]
EOF

Finally, go back to the application directory and let’s build our Javascript library.

$ cd ../main
$ npm run dev

Once npm has finished, you can start your Django application and fire up a web browser

$ cd ..
$ ./manage.py runserver