Get started with Django + React Js

I recently started a new web project based on both Django and React.Js. It took a good deal of reading half-related and/or outdated posts, tons of documentation, and a good deal of trial and error to get it right.

In this I will cover the key points on setting up a nice and solid development environment . The specifics of how to deploy.

We will be using multiple libraries in this project, mainly, django-rest-framework for creating APIs easily, react-router-dom for handling in-app routing, redux for maintaing global application state.


Setup step:

Django Setup

  1. We need python 2.7 or python 3.x ( Assuming python installed)
  2. Create virtual environment (refer https://pypi.python.org/pypi/virtualenv)
  3. Activate virtual env. (/virtu-env-dir/bin/active)
  4. Start installing pip install django

Now, we will create a project called sample_react using django-admin tool.

$ django-admin startproject sample_react

Now run all migrate command and then runserver. then django will start working.

$ cd sample_react

$ python manange.py migrate

$ python manage.py runserver

now django started at http://127.0.0.1:8000

Setup react with Webpack

I would like to add little intro about webpack ,

  • Webpack is now the defacto tool to for module bundling, compiling all your dependencies to a small bundles . You can find more about it at official website.
  • When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into a small number of bundles — often only one — to be loaded by the browser.

we will use create-react-app to generate the project boilerplate with all the configurations in it.

sudo npm install -g create-react-app

Now we will create Front End Application using react

$ create-react-app frontend
$ cd frontend
$ npm run start

Here app will start at http://localhost:3000

Integrating Django with React

Now back to django project. We will use django-webpack-loader a django application which injects link and script tag for the bundles which webpack generates dynamically.

(sample_env)$ pip install django-webpack-loader

Now add following in sample_react/settings.py

WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'bundles/',
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.dev.json'),
}
}

Also add webpack_loader in INSTALLED_APPS

Also need template setting for view

TEMPLATES = [
{
# ... other settings
'DIRS': [os.path.join(BASE_DIR, "templates"), ],
# ... other settings
},
]

Then add index.html in sample_react/templates/index.html

Add following snippest in that file

{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Test Project</title>
</head>
<body>
<div id="root">
    </div>
{% render_bundle 'main' %}
</body>
</html>

Now we need to create view for serve this page. add following in sample_react/urls.py

from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView

urlpatterns = [
url(r'^', TemplateView.as_view(template_name="index.html")),
]

Now in frontend dir install : webpack-bundle-tracker . We’ll be using webpack-bundle-tracker to extract information from webpack and django-webpack-loader to use the extracted information for django integration.

$ npm install webpack-bundle-tracker --save-dev

In your frontend/config/paths.js add the following key and value in the module.exportsobject.

module.exports = {
// ... other values
statsRoot: resolveApp('../'),
}

In frontend/config/webpack.config.dev.js change publicPath and publicUrl to http://localhost:3000/

const publicPath = 'http://localhost:3000/';
const publicUrl = 'http://localhost:3000/';

In the same file, import webpack-bundle-tracker and include BundleTracker in webpack plugins and replace webpackHotDevClient line with the other two modules.

const BundleTracker = require('webpack-bundle-tracker');
module.exports = {
entry: [
// ... KEEP OTHER VALUES
require.resolve('webpack-dev-server/client') + '?http://localhost:3000',
require.resolve('webpack/hot/dev-server'),
// require.resolve('react-dev-utils/webpackHotDevClient'),
],
plugins: [
// ... other plugins
new BundleTracker({path: paths.statsRoot, filename: 'webpack-stats.dev.json'}),
],
}

The reason of replacing webpackHotDevClient, publicPath and publicUrl is that we are going to serve webpack dev server's bundle on a django page, and we don't want webpack hot loader to send requests to wrong url/host.

Now in frontend/config/webpackDevServer.config.js we need to allow the server to accept requests from external origins. http://localhost:8000 (Django server) will send XHR requests to http://localhost:3000 webpack server to check for source file changes.

Put headers object in the object returned by the exported function. This object is to be placed at the same level of https and host properties.

headers: {
'Access-Control-Allow-Origin': '*'
},

That’s it. Stop the webpack server and run it again and go to http://localhost:8000/, you should see the same react welocme page as you did on webpack server page.

Now, any changes you do in src/App.js file will be instantly reflected on the opened page in browser using hot loading.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to Sample Project</h1>
</header>
<p className="App-intro">
A react app with django.
</p>
</div>
);
}
}
export default App;