A little Python module helping to use Django and React on a single port during development and production
Project description
logicore-django-react
A little Python module helping to use Django and React on a single port during development and production
Serves as a foundation for logicore-django-react-pages project, but can be used without it
Running Django and React on a single port during development
TODO: Motivation
Usage from scratch: starting a Django + React project for development
TODO: automated script/project template
- Install Django and start the project
mkvirtualenv django_react_project1 # Or venv etc
python3 -m pip install Django
django-admin.py startproject django_react_project1
cd django_react_project1
# Configure database, etc and commit
Now you have fresh Django! Check it works:
python manage.py runserver
and stop the development server.
Hint: Don't forget to add minimal .gitignore
file for Python/Django development, such as:
*.swp
*.py[cod]
__pycache__
*.sqlite3
/static/**
/media/**
- Make a React for-development installation (inside a Django folder), called
frontend
. Then, commit the changes and eject (we need it all):
create-react-app frontend
git add --all :/ && git commit -m "added frontend"
cd frontend
yarn eject
git add --all :/ && git commit -m "ejected frontend"
- Install
logicore_django_react
and make use of it from your Django project:
pip install -U logicore_django_react
(-U
is required to ensure to get latest version)
Add to urls.py
:
from logicore_django_react.urls import react_reload_and_static_urls, react_html_template_urls
urlpatterns = [
# ...
]
# add static/media endpoints here if needed
# urlpatterns += static(...)
# lastly, combine with logicore_django_react urls
urlpatterns = react_reload_and_static_urls + urlpatterns + react_html_template_urls
Which will add necessary views for React to work via Django:
react_reload_and_static_urls
— serves hot-reload hooks and static filesreact_html_template_urls
— global (aka match-all,.*
) view, that just serves HTML template that includes React
The latter (HTML template) might be overridden by changing
the LOGICORE_DJANGO_REACT_TEMPLATE
setting, which is by default set to
logicore_django_react/home.html
filename.
Please see source of a corresponding template file as an example.
Important: In order for template file and template tags to work, add logicore_django_react
to INSTALLED_APPS
.
Also to settings, add:
FRONTEND_DEV_MODE = os.environ.get("FRONTEND_DEV_MODE", None)
(otherwise you may see an error message).
This environment variable is required to distinguish if Django is running in development or production mode.
- Either:
- create your main app in Django (e.g. called
main
) - or add non-app templates and static folders
to prepare for React build bundles (templates and static files) to be saved into and remember it for the next step:
python manage.py startapp main # and add to INSTALLED_APPS
mkdir main/templates/ # here, "react" folder will automatically be added later
mkdir main/static/ # here, "react" folder will automatically be added later
or
# add "my_global_templates" to TEMPLATE_DIRS
mkdir my_global_templates/ # here, "react" folder will automatically be added later
# add "my_global_static" to STATICFILES_DIRS
mkdir my_global_static/ # here, "react" folder will automatically be added later
Hints:
- When creating an app, don't forget to add it to
INSTALLTED_APPS
- gitkeep the templates/static folders created
- Make modifications to
frontend
sub-project:
- in frontend/config/env.js — replace:
WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,
by
WDS_SOCKET_PORT: 3000,
This will make React project's built-in websocket to the right port — where the React's server is and not e.g. 8000.
- In
frontend/scripts/start.js
comment outopenBrowser
command. Before:
openBrowser(urls.localUrlForBrowser);
after:
//openBrowser(urls.localUrlForBrowser);
which doesn't open a browser at port 3000
, 'cause we don't want direct output
of React's dev server (it will be got by Django instead).
- make the following modifications to
frontend/scripts/build.js
file (to make build process also integrate with Django):- Add to the beginning:
const rimraf = require('rimraf');
const mkdirp = require('mkdirp');
- and also, install that modules (inside your
frontend
folder):
yarn add -D rimraf mkdirp
- before the first
.catch(...)
statement in the file, prepend the following extra step:
.then(function () {
const filename = __dirname + '/../build/asset-manifest.json';
const chunks = {};
JSON.parse(fs.readFileSync(filename)).entrypoints.map(e => {
let ext = e.split('.');
ext = ext[ext.length - 1];
if (!chunks[ext]) chunks[ext] = [];
chunks[ext].push(e.replace('static/', '/static/react/'));
});
const appBase = __dirname + '/../../main/';
const templates = {
css: url => `<link rel="stylesheet" type="text/css" href="${url}" />`,
js: url => `<script type="text/javascript" src="${url}"></script>`,
}
for (let [k, v] of Object.entries(templates)) {
const html = chunks[k]?.map(v).join('');
const fileDir = `${appBase}templates/react/`;
mkdirp.sync(fileDir);
fs.writeFileSync(`${fileDir}bundle_${k}.html`, html);
}
const srcDir = __dirname + '/../build/static/';
const destDir = appBase + 'static/react/';
console.log(`will remove dir ${destDir}`);
rimraf.sync(destDir);
fs.copySync(srcDir, destDir, { overwrite: true }, function (err) {
if (err) {
console.error(err);
} else {
console.log(chalk.green("copy assets to build: success!"));
}
});
})
and check that the path __dirname + '/../../main/
(the appBase
) points exactly to where your
location for auto-generated (during the build) templates and static files is.
This example is given for storing the files inside the folders of an app called main
.
- Finally, in
frontend/config/webpack.config.js
replace two occurrences ofstatic/media/
byreact-static/media/
:
assetModuleFilename: 'static/media/[name].[hash][ext]',
to
assetModuleFilename: 'react-static/media/[name].[hash][ext]',
and
name: 'static/media/[name].[hash].[ext]',
to
name: 'react-static/media/[name].[hash].[ext]',
to give specifically included static files, such as included images their own directory
('cause static
may be already taken by Django).
- gitignore the auto-generated folders of yours:
main/templates/react/**
main/static/react/**
- Add files and commit — now you should have ready-to-go setup for developing and deploying Django + React project on a single port!
Development
In root folder:
export FRONTEND_DEV_MODE=1
python manage.py runserver
In frontend/
folder:
yarn start
Production
- Build frontend and collect static
cd frontend/
yarn build
cd ..
python manage.py collectstatic
- Deploy as normal (according to Django docs)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for logicore-django-react-1.0.0.dev23.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6a314924f049813fc9b1460a3da2ff68f1bb087760b26b0c83eda4735679ec6f |
|
MD5 | ea48ad4c1194b2b90ee222ae5fe3f0b7 |
|
BLAKE2b-256 | 2ec2aece04e32404e33c018c9449fb68796b7b60602c9437dfc8e9fe6ef36c80 |
Hashes for logicore_django_react-1.0.0.dev23-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | acb359912a63e7ff68f1f73bf3791572514ce514e1459bc2e9ecdcdbb38a3214 |
|
MD5 | f072187160663a38d55500da5e157fa8 |
|
BLAKE2b-256 | 2d03424eea4bcfc5d11778dfa44f5d5be9417b9c8f954a8c643bba835bd13e2e |