The ReactJS structure based on Javascript has gained increased popularity over the last couple of years. And rightfully so — it is a very flexible and, without modesty, perfect solution for the creation of Single Page Applications, also very popular at the moment. React also helps develop interactive web apps with impeccable performance due to the server-side rendering. Add on top of that, with support by the Facebook team as well as an extensive online community, you can see for yourself how utterly efficient it can be for the frontend development of web apps.
Nevertheless, React alone isn’t enough to build fully-featured web software. An API must also be integrated with the created frontend to provide server interaction and data transfer. We, similarly to a multitude of developers, prefer a Python-based framework, Django Rest, for this task, invented especially for backend development.
Despite Django and React basically being two independent structures, a frontend and backend written with the help of each work together pretty well. We prepared a brief tutorial where we tell you how to use React with Django.
Up until frontend frameworks first appeared in the field of IT development, all of the business logic of applications worked on the server side exclusively. The UI only had to display certain reactions to user requests. When solutions like React and Angular appeared, the web app construction approach experienced significant changes. The process of user-server interaction became more advanced. A synchronization of user input with user interface elements started being implemented in the frontend software code.
This allowed significantly accelerating web soft performance and provided a brand-new level of UX. It also made the developers’ job easier — apps written with the help of this method are much more scalable in nature.
As to the React and Django pair, it’s practically a canonical combination for building web software globally. The thing is, both Python and Django feature a steep learning curve, vast online community, and a good set of built-in tools that allow users to focus on the construction of software logic instead of other, more trivial aspects.
React is quite accessibly integrated with Django. Moreover, this framework is praised for its very rapid rendering (as opposed to that provided by Angular, for instance), accessible learning curve and advanced flexibility (which, however, can spawn certain difficulties for inexperienced developers like in-depth code errors).
Well, have we convinced you that Django with React is worth your attention? Then let’s get to some tips for the creation of a backend (via Django) and frontend (via React).
First things first — install the Django framework and connect the database in the following manner:
$ virtualenv env
$ source env/bin/activate
$ pip3 install django djangorestframework django-filter
$ pip3 freeze > requirements.txt
Now we can open our project and launch the application:
$ django-admin startproject backend
$ cd backend
$ django-admin startapp api
The next step would be the configuration of the selected database in accordance with Django working requirements plus the configuration of DRF.
Now, to one of the most important aspects of software creation — the authentication procedure. In our example, we are taking a look at authentication with the use of tokens. This isn’t the most reliable option because tokens are stored on the server end for an unlimited time — if some hacker finds this weak point in your solution, they will successfully hack it. On the other hand, this method of authentication allows us to demonstrate a way to provide the connection between the UI and server side through an API. Read about how to configure tokens on the Django official website.
See how the authentication procedure with the help of tokens can be implemented below — particularly, the importance of a name and password of a certain user in your redux Store:
# file: api/urls.py
from django.conf.urls import ur
l
from rest_framework.authtoken import views as drf_views
urlpatterns = [
url(r'^auth$',
drf_views.obtain_auth_token, name='auth'),
]
The next step would the definition of urlpatterns:
# file: backend/urls.py
from django.conf.urls import url, include
urlpatterns = [
url(r'^', include('api.urls', namespace='api', app_name='api')),
]
Adding this code to the project, you teach your software to track resource location indicators.
The following lines are for testing the app performance — they launch the performance of the server end, however, the testing itself can only be launched once the frontend has been worked on.
$ python3 manage.py migrate
$ python3 manage.py createsuperuser
$ python3 manage.py runserver 0.0.0.0:8000
Once you’ve written the code for the server end, you can easily check where your resource is located via the following command:
$ curl -X POST -d "username=username&password=password"
http://localhost:8000/auth
Let’s start with the definition of how the commonly known feature create-react-app will be used in our code. Notice also that you’ll have to delete default content in the configuration files (we believe this will give you much more flexibility in the further development of frontend performance).
$ npm install -g create-react-app
$ create-react-app frontend
$ cd frontend
$ npm run eject
Setting up dependencies you’ll find useful further on:
$ npm install --save-dev babel-preset-es2015 babel-preset-stage-3
$ npm install --save redux redux-logger redux-persist response-redux
$ npm install --save axios response-router-dom lodash
Consider the part of code responsible for the connection of backend and frontend. The first thing to do would be to create a redux Store where you’ll carry out the procedure of storing tokens with user data (which an app receives upon authentication):
// file: src/store.js
import { compose, createStore, applyMiddleware } from 'redux';
import { createLogger } from 'redux-logger';
import { persistStore, autoRehydrate } from 'redux-persist';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
compose(
applyMiddleware
(
createLogger()
,
),
autoRehydrate()
)
);
persistStore(store);
export default store;
// file: src/reducers/index.js
import { combineReducers } from 'redux';
import * as actionType from '../actions/types';
const tokenInitialState = null;
const token = (state = tokenInitialState, action) => {
switch(action.type) {
case actionType.SET_TOKEN:
return action.data;
default:
return state;
}
}
const appReducer = combineReducers({
token,
})
const rootReducer = (state, action) => {
return appReducer(state, action);
}
export default rootReducer;
Next, define actions that must be entered in the form of code into files index.js and types.js:
// file: src/actions/index.js
import * as actionType from './types';
export const setToken = (data) => {
return {
type: actionType.SET_TOKEN,
data
}
}
// file: src/actions/types.js
export const SET_TOKEN = "SET_TOKEN";
Above is the definition of how the solution would act to define the processing of tokens with user data during authentication. Particularly, you can see the way they are being saved on the server end.
Now for the lines you’ll need to describe user authorization processes (they include the exceptions processor in which the app behavior upon input of invalid data is defined).
// file: src/util/Auth.js
import axios from 'axios';
import _ from 'lodash';
import store from '../store';
import { setToken } from '../actions'
import { URL, LOGIN } from '../config/Api';
export function InvalidCredentialsException(message) {
this.message = message;
this.name = 'InvalidCredentialsException';
}
export function login(username, password) {
return axios
.post(URL + LOGIN, {
username,
password
})
.then(function (response) {
store.dispatch(setToken(response.data.token));
})
.catch(function (error) {
// raise different exception if due to invalid credentials
if (_.get(error, 'response.status') === 400) {
throw new InvalidCredentialsException(error);
}
throw error;
});
}
export function loggedIn() {
return store.getState().token == null;
}
These lines of code allow redux Store tokens to be sent, and, in such a manner, give us the ability to set up an interconnection with authorized users from any place in your solution’s user part.
// file: src/util/ApiClient.js
import axios from 'axios';
import store from '../store';
import { URL } from '../config/Api';
export const apiClient = function() {
const token = store.getState().token;
const params = {
baseURL: URL,
headers: {'Authorization': 'Token ' + token}
};
return axios.create(params);
}
These two chunks of code employ the file including definitions of constants. This file makes it simpler to read the code and reduce the chance of errors due to improper redefinition of variables (in the case of constants, they are redefined once in the ../config/Api file).
export const URL = process.env.API_URL;
export const LOGIN = "/ auth";
That’s it. You have successfully established the interconnection between backend and frontend using React with Django. Now, you may test the created solution. Just enter the system and enter your authentication data into the respective lines. If everything works correctly, you can open a browser upon the repeated launch of the app in developer mode and see that a token has been transferred to the redux Store servers.
As you can see, people more or less acquainted with React, Redux, Django, and DRF won’t experience much difficulty in implementing the above-described example. On the other hand, if you’re an inexperienced web developer starting out and want to build a commercial solution — turn to professionals.
Originally published at sloboda-studio.com on August 7, 2018.