Skip to main content

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

  1. 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/**
  1. 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"
  1. 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 files
  • react_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.

  1. 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
  1. 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 out openBrowser 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 of static/media/ by react-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).

  1. gitignore the auto-generated folders of yours:
main/templates/react/**
main/static/react/**
  1. 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

  1. Build frontend and collect static
cd frontend/
yarn build
cd ..
python manage.py collectstatic
  1. Deploy as normal (according to Django docs)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

logicore-django-react-1.0.0.dev23.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

logicore_django_react-1.0.0.dev23-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file logicore-django-react-1.0.0.dev23.tar.gz.

File metadata

File hashes

Hashes for logicore-django-react-1.0.0.dev23.tar.gz
Algorithm Hash digest
SHA256 6a314924f049813fc9b1460a3da2ff68f1bb087760b26b0c83eda4735679ec6f
MD5 ea48ad4c1194b2b90ee222ae5fe3f0b7
BLAKE2b-256 2ec2aece04e32404e33c018c9449fb68796b7b60602c9437dfc8e9fe6ef36c80

See more details on using hashes here.

File details

Details for the file logicore_django_react-1.0.0.dev23-py3-none-any.whl.

File metadata

File hashes

Hashes for logicore_django_react-1.0.0.dev23-py3-none-any.whl
Algorithm Hash digest
SHA256 acb359912a63e7ff68f1f73bf3791572514ce514e1459bc2e9ecdcdbb38a3214
MD5 f072187160663a38d55500da5e157fa8
BLAKE2b-256 2d03424eea4bcfc5d11778dfa44f5d5be9417b9c8f954a8c643bba835bd13e2e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page