Make a Django app as usual
When working with React, Django mainly serves as an API. Django REST framework is a must.
Make a React app as usual
The react app can be created with create-react-app
, it doesn't really matter. Whenever you need to make an API request to get data to render, fetch it from the API you just made with Django. Of course you can use dummy data if you start off with React instead of Django.
Integration
There should be at least 3 folders in your Django app:
-
project/project
folder, meaning the one withsettings.py
-
project/api
folder, the one with the apimodels.py
,serializers.py
etc. -
project/frontend
folder, it's created bymanage.py startapp frontend
command and in this folder, more folders should be created:
-
src
folder: contains anindex.js
file and all other react components insrc/components
folder -
static/frontend
folder: wheremain.js
file lives after you runnpm run build
ornpm run dev
(depends on the script you write --> keep reading) -
templates/frontend
folder: where you store your django templateindex.html
, remember you can use django template language/syntax in these html files
Reminders - Make sure:
- you added
frontend
app in yoursettings.py
- added
{% load static %}
and<script src="{% static 'frontend/main.js' %}></script>
inindex.html
- added
index
function in yourviews.py
file - added according url patters in your
urls.py
file - included url patterns in
frontend/urls.py
intoproject/urls.py
file
Webpack configuration:
Assuming you've had Node.js
installed
1. package.json
$ npm init -y
To create a package.json
file with all your javascript dependencies, -y
means to install the defaults and not answering any questions
Now the package.json
file looks like this:
{
"name": "frontend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
2. install webpack
and webpack-cli
$ npm i -D webpack webpack-cli
-D
means to install as Development dependencies
Now a new key added to package.json
file:
{
// ...
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
3. install babel
and react preset
$ npm i -D @babel/core babel-loader @babel/preset-env @babel/preset-react babel-plugin-transform-class-properties
-
@babel/core
: the babel core package -
babel-loader
: helps to transpile the code -
@babel/preset-env
: compile down ES6 to be compatible with other versions -
@babel/preset-react
: react preset -
babel-plugin-transform-class-properties
: handles static class properties for ES2015 and ES2016
Now the package.json
file looks like this:
{
// ...added in step 1
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"@babel/preset-react": "^7.9.4",
"babel-loader": "^8.1.0",
"babel-plugin-transform-class-properties": "^6.24.1"
// ...added in step 2
}
}
4. install react
and react-dom
$ npm i react react-dom prop-types
- prop-types: > Runtime type checking for React props and similar objects.
Now the package.json
file looks like this:
{
// ...added in stop 1,2,3
"dependencies": {
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1"
}
}
In my project, I also installed other dependencies: $ npm i react-router-dom react-markdown react-syntax-highlighter react-spring styled-components
And you might need to install more loaders for different file types:
-
$ npm i -D style-loader css-loader
for css files -
$ npm i -D file-loader url-loader
for image files
5. create file: .babelrc
In order to use the previously installed presets and plugin, we need to create a .babelrc
file.
~/project/frontend/.babelrc
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["transform-class-properties"]
}
6. create file: webpack.config.js
Whenever you use webpack
you'll have this config file. All we want to do here is to load babel-loader
:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
],
},
};
What the object does:
-
test
: a regular expression to look through all of the js files -
exclude
: excludenode_modules
folder -
use
: thebabel-loader
to transpile our code
The above is the simplest webpack config file. In real cases, there must be more loaders
installed, you can refer to the offical document for more information. At the end, my webpack.config.js
becomes:
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
{
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 8192,
},
},
],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
7. write scripts
in package.json
To compile our React app which lives in the frontend
app, some scripts have to be defined:
~/project/frontend/package.json
{
// ...
"scripts": {
"dev": "webpack --mode development --watch ./src/index.js --output ./static/frontend/main.js",
"build": "webpack --mode production ./src/index.js --output ./static/frontend/main.js"
}
// ...
}
The scripts defined above would enable us the following commands:
-
$ npm run dev
: runwebpack
, use--mode development
,--watch
every updates in./src/index.js
file, and compile it to./static/frontend/main.js
file -
$ npm run build
: does a few extra thing for production
8. $ npm run dev
After this script is run, main.js
file will be ready to use.
Notes on routing
- In the MAIN
urls.py
file, include the frontend urls at then end - Use
re_path()
method in frontendurls.py
file to define the url pattern - Use extra 'negative lookahead' to exclude api calls in order to avoid url clash between different django apps (in this case the
frontend
app and myapi
app which serves the api calls):re_path(r'^(?!api)(?:.*)/?$', views.index),
A remember of npm
commands
npm uninstall <name>
removes the module fromnode_modules
but does not updatepackage.json
npm uninstall <name> --save
also removes it fromdependencies
inpackage.json
npm uninstall <name> --save-dev
also removes it fromdevDependencies
inpackage.json
npm uninstall -g <name> --save
also removes it globally
Top comments (0)