diff --git a/README.rst b/README.rst index 5aef5fd..94ded8f 100644 --- a/README.rst +++ b/README.rst @@ -1,135 +1,171 @@ -|pythonapp| +Making React a First-Class Citizen in Django CMS with React Router Integration +=============================================================================== -##################### -django CMS quickstart -##################### +Introduction +------------ -- A dockerised django CMS project intended to be run locally in Docker on your own machine or on a Docker-based cloud, such as `Divio `_ -- This version uses Python 3.11 and the most up-to-date versions of Django 4.2, and django CMS 4.1.0 -- This project is endorsed by the `django CMS Association `_. That means that it is officially accepted by the dCA as being in line with our roadmap vision and development/plugin policy. Join us on `Slack `_ for more information or questions. -- The documentation for django CMS can be found here: https://docs.django-cms.org/ +Django CMS is a powerful content management system that excels at structured, editorial content. +However, modern frontend experiences often demand the flexibility and interactivity of React. -Installation -############ +In this post, we'll walk through how React — along with React Router — can be integrated as +first-class citizens in a Django CMS project, so that your editors and frontend engineers +can both thrive. -Requirements -============ +Why Integrate React with Django CMS +----------------------------------- -You need to have Docker installed on your system to run this project. +- Django CMS provides content structure, versioning, and editorial workflows. +- React enables interactive, dynamic UIs with modern developer ergonomics. +- Common use cases: -- `Install Docker `_ here. -- If you have not used docker in the past, please read this - `introduction on docker `_ here. + - Embedding a dashboard or widget inside CMS-managed pages. + - Creating fully dynamic web apps that live at certain CMS-defined routes. + - Building reusable React-based plugins inside Django CMS placeholders. -Local Setup -=========== +Approach Overview +----------------- -.. inclusion-marker-do-not-remove +There are two major strategies: -.. code-block:: bash +- **SPA-in-CMS:** Let Django CMS render the base HTML layout and inject React into a placeholder. +- **CMS-in-SPA:** Use Django CMS as a headless backend and build everything with React. - git clone git@github.com:django-cms/django-cms-quickstart.git - cd django-cms-quickstart - docker compose build web - docker compose up -d database_default - docker compose run --rm web python manage.py migrate - docker compose run --rm web python manage.py createsuperuser - docker compose up -d +In this guide, we'll use the **SPA-in-CMS** approach, where React is bootstrapped inside +a Django CMS placeholder and React Router manages the internal routing. -Then open http://django-cms-quickstart.127.0.0.1.nip.io:8000 (or just http://127.0.0.1:8000) in your browser. +Project Setup +------------- -You can stop the server with ``docker compose stop`` without destroying the containers and restart it with -``docker compose start``. +1. Setup Django CMS (you can use `djangocms-installer` or your custom setup). +2. Create a React app: -With ``docker compose down`` the containers are deleted, but the database content is still preserved in the named -volume ``django-cms-quickstart_postgres-data`` and the media files are stored in the file system in ``data/media``. -Then you can update the project e. g. by changing the requirements and settings. Finally you can rebuild the web image -and start the server again: + - With `create-react-app`, Vite, or Webpack. +3. Integrate using either: -.. code-block:: bash + - `django-webpack-loader` (Webpack), + - or `django-vite`. - docker compose build web - docker compose up -d +Serving React from Django CMS +----------------------------- +- Create a Django CMS plugin that renders a `
` in a placeholder. +- This div acts as the mounting point for the React app. +- Your CMS template might look like: -Note: Since Compose V2, ``docker-compose`` is now included inside docker. For more information, checkout the -`Compose V2 `_ Documentation. + .. code-block:: html -.. inclusion-end-marker-do-not-remove + {% load render_placeholder %} + + + {% render_placeholder "main" %} + + + -Customising the project -####################### +- You can also pass page or context data from the backend to React via `data-*` attributes or global JS variables. -This project is ready-to-go without making any changes at all, but also gives you some options. +React Router Configuration +-------------------------- -As-is, it will include a number of useful django CMS plugins and Bootstrap 4 for the frontend. You don't have to use -these; they're optional. If you don't want to use them, read through the ``settings.py`` and ``requirements.txt`` files -to see sections that can be removed - in each case, the section is noted with a comment containing the word 'optional'. +- Wrap your React app with `` or ``. +- Configure a base path if the React app lives under a CMS-defined URL like `/app/`. +- Example: -Options are also available for using Postgres/MySQL, uWSGI/Gunicorn/Guvicorn, etc. + .. code-block:: jsx -Updating requirements -===================== + import { BrowserRouter, Routes, Route } from 'react-router-dom'; -The project uses a django best practise two step approach, freezing all dependencies with pip-tools. Here is how to update requirements: + const App = () => ( + + + } /> + } /> + + + ); -1. Change ``requirements.in`` according to your needs. There is no need to pin the package versions here unless you have a good reason (i.e. known incompatibilities) -2. Run ``docker compose run --rm web pip-compile requirements.in >> requirements.txt`` -3. ``requirements.txt`` should now have changed -4. Rebuild the container ``docker compose build web`` and restart ``docker compose up -d`` +Handling Routing Conflicts +-------------------------- -Features -######## +- Prevent Django from trying to resolve React's client-side routes. +- Add a CMS page with the URL `/app/` and insert your React plugin there. +- Any sub-routes like `/app/profile` will be handled by React Router. -Static Files with Whitenoise -============================ +Advanced Considerations +----------------------- -- This quickstart demo has a cloud-ready static files setup via django-whitenoise. -- In the containerized cloud the application is not served by a web server like nginx but directly through uwsgi. django-whitenoise is the glue that's needed to serve static files in your application directly through uwsgi. -- See the django-whitenoise settings in settings.py and the ``quickstart/templates/whitenoise-static-files-demo.html`` demo page template that serves a static file. +- **SEO/SSR**: React apps are client-side rendered; for SEO-heavy use cases, consider SSR or pre-rendering. +- **i18n**: Pass `language_code` from Django CMS to React, and use libraries like `react-i18next`. +- **Context sync**: Provide CMS context to React via props, global config, or context providers. -Env variables -============= +Example Configuration Snippets +------------------------------ -- By default, Docker injects the env vars defined in ``.env-local`` into the quickstart project. -- If you want to access the PostgreSQL database from the host system, set ``DB_PORT`` to the desired port number. - 5432 is the standard port number. If you run PosgreSQL on your host system, you may want to set another port number. - If this variable is empty (the default), the PosgreSQL instance in the container is only reachable within docker, but - not from outside. +- **Webpack:** -Contribution -############ + .. code-block:: js -Here is the official django CMS repository: -`https://github.com/django-cms/django-cms-quickstart/ `_. + // webpack.config.js + output: { + publicPath: '/static/webpack_bundles/', + } +- **settings.py:** -Deployment -########## + .. code-block:: python -Note that this is just a demo project to get you started. It is designed to be run locally through docker. If you want a full production ready site with all the bells -and whistles we recommend you have a look at https://github.com/django-cms/djangocms-template instead. + INSTALLED_APPS += ['webpack_loader'] + WEBPACK_LOADER = { + 'DEFAULT': { + 'BUNDLE_DIR_NAME': 'webpack_bundles/', + 'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'), + } + } -Some deployment hints: +- **CMS Template:** -- To deploy this project in testing mode (recommended) set the environment variable ``DEBUG`` to ``True`` in your hosting environment. -- Be aware that if ``DEBUG`` is false, django requires you to whitelist the domain. Set the env var ``DOMAIN`` to the host, i.e. ``www.domain.com`` or ``*.domain.com``. -- You can set the env var ``DEFAULT_STORAGE_DSN`` to something meaningful (i.e. for s3 file storage) + .. code-block:: html -Deployment Commands -=================== +
-Configure your hosting environment to run the following commands on every deployment: +- **React App Entry:** -- ``./manage.py migrate`` + .. code-block:: js + import ReactDOM from 'react-dom/client'; + import App from './App'; -Divio Deployment -================ + const root = document.getElementById('react-root'); + ReactDOM.createRoot(root).render(); -divio.com is a cloud hosting platform optimized for django web applications. It's the quickest way to deploy this -project. Here is a `video tutorial `_ and a -`description of the deployment steps `_ that are mostly applicable for this quickstart project. +Deployment Tips +--------------- +- Run `npm run build` (or Vite equivalent). +- Collect static files via `collectstatic`. +- Optionally serve assets via CDN. +- Avoid client/server routing conflicts by keeping React confined under predictable base paths. -.. |pythonapp| image:: https://github.com/django-cms/django-cms-quickstart/workflows/Python%20application/badge.svg?branch=support/cms-4.1.x +Conclusion +---------- + +By carefully integrating React into Django CMS via placeholders and using React Router for +client-side navigation, you can build rich, dynamic UIs within an editorially friendly platform. + +This hybrid setup lets you enjoy the best of both worlds — clean backend content structure +and dynamic, reactive frontends. + +Optional Appendix +----------------- + +- Example repo link (if any) +- Troubleshooting: + + - Missing static files? + - Routing conflicts? + - React Router not picking up URL paths? + +- Future ideas: + + - Use of Next.js or RSC (React Server Components). + - CMS-driven metadata injection for SSR.