- Notifications
You must be signed in to change notification settings - Fork3
django-cms/djangocms-rest
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
djangocms-rest enables frontend projects to consume django CMS content through a browsableread-only, REST/JSON API. It is based on the django rest framework (DRF) and supports OpenAPI3 schema generation via drf-spectacular.
✨ Key Features
💫Django CMS 4 and 5 Support – Including latest version support (5.0)
🏢Multi-site support – Supports Django sites
🌍Internationalization (i18n) – Supports available CMS languages
🌲Structured page tree – Fetch the full page tree with metadata
📚Paginated page listing – Retrieve pages as a list with pagination support
🔄Built-in caching - Uses django cache backend for placeholder serialization/rendering
👀Preview support – Access draft content usingdjangocms-versioning
supportingpermissions for authenticated staff user
🧬Typed API schema – Auto-generate OpenAPI schemas for pages and plugins withdrf-spectacular
🧩Flexible responses – Fetch plugin content as JSON or fully rendered HTML
⚠️ Note
djangocms-rest
is under active development. Since the API is read-only, it's safe to explorewithout risk of unintended data changes.
A Headless CMS (Content Management System) is a backend-only content management system that providescontent through APIs, making it decoupled from the front-end presentation layer. This allowsdevelopers to deliver content to any device or platform, such as websites, mobile apps, or IoTdevices, using any technology stack. By separating content management from content presentation,a Headless CMS offers greater flexibility and scalability in delivering content.
Used withdrf-spectacular
, djangocms-rest generates complete OpenAPI schemas for both DRFendpoints and Django CMS content plugins. This allows seamless, typed integration withTypeScript-friendly frameworks.
Running a CMS in headless mode offers several advantages, particularly for projects that requireflexibility, scalability, and multi-platform content delivery:
Benefits of running Django CMS in headless mode:
- Flexible content delivery to multiple platforms and devices via APIs, enabling consistentmulti-channel experiences.
- Independent development of frontend and backend using best-suited technologies, improvingscalability and team efficiency.
- Improved performance through optimized frontend rendering and decoupled architecture.
- Streamlined content management, allowing editors to update content across applications withouttouching the infrastructure.
- Easier integration with modern frameworks (e.g., React, Nuxt, Next.js) and third-party services.
First, consider whether the benefits of a headless system outweigh the cost of running two separatetech stacks for frontend and backend. For larger projects or when working in teams, having aseparation of concerns across different domains can be a significant advantage. However, for smallerprojects, this is often not the case.
Limitations and considerations in headless mode:
- Inline editing and content preview are currently only available in a structured view. (Solutionsare currently being evaluated).
- Not all features of a standard Django CMS are available through the API (eg. templates and tags).
- The API focuses on fetching plugin content and page structure as JSON data.
- Website rendering is entirely decoupled and must be implemented in the frontend framework.
Are there js packages for drop-in support of frontend editing in the javascript framework of my choice?
The good news first: django CMS headless mode is fully backend supported and works independentlyof the javascript framework. It is fully compatible with the javascript framework of your choosing.
It's pretty much the same as for a traditional django CMS project, seehere for instructions on how to create django CMS plugins.
Let's have an example. Here is a simple plugin with two fields to render a custom header. Pleasenote that the template included is just a simple visual helper to support editors to managecontent in the django CMS backend. Also, backend developers can now toy around and test theirdjango CMS code independently of a frontend project.
After setting up djangocms-rest and creating such a plugin you can now run the project and see aREST/JSON representation of your content in your browser, ready for consumption by a decoupledfrontend.
cms_plugins.py
:
# -*- coding: utf-8 -*-from cms.plugin_base import CMSPluginBasefrom cms.plugin_pool import plugin_poolfrom . import modelsclass CustomHeadingPlugin(CMSPluginBase): model = models.CustomHeadingPluginModel module = 'Layout Helpers' name = "My Custom Heading" # this is just a simple, unstyled helper rendering so editors can manage content render_template = 'custom_heading_plugin/plugins/custom-heading.html' allow_children = Falseplugin_pool.register_plugin(CustomHeadingPlugin)
models.py
:
from cms.models.pluginmodel import CMSPluginfrom django.db import modelsclass CustomHeadingPluginModel(CMSPlugin): heading_text = models.CharField( max_length=256, ) size = models.PositiveIntegerField(default=1)
templates/custom_heading_plugin/plugins/custom-heading.html
:
<h{{ instance.size }}>{{ instance.heading_text }}</h{{ instance.size }}>
Yes, djangocms-rest provides out of the box support for any and all django CMS plugins whose contentcan be serialized.
Yes, djangocms-text has both HTML blob and structured JSON support for rich text.
URLs to other CMS objects are dynamic, in the form of<app-name>.<object-name>:<uid>
, for examplecms.page:2
. The frontend can then use this to resolve the object and create the appropriate URLsto the object's frontend representation.
I don't need pages, I just have a fixed number of content areas in my frontend application for which I need CMS support.
Absolutely, you can use the djangocms-aliases package. It allows you to define customplaceholdersthat are not linked to any pages. djangocms-rest will then make a list of those aliases and theircontent available via the REST API.
- Python
- Django
- Django CMS
Install using pip:
pip install git+https://github.com/django-cms/djangocms-rest@main
Update yourINSTALLED_APPS
setting:
INSTALLED_APPS= [ ...'djangocms_rest','rest_framework', ...]
# Enabled CachingCONTENT_CACHE_DURATION=60# Overwrites default from django CMSCACHES= {'default': {'BACKEND':'django.core.cache.backends.locmem.LocMemCache',# use redis/memcached etc.'LOCATION':'unique-snowflake','TIMEOUT':CONTENT_CACHE_DURATION,# change accordingly }}
Add the API endpoints to your project'surls.py
:
fromdjango.urlsimportpath,includeurlpatterns= [ ...path('api/',include('djangocms_rest.urls')), ...]
Navigate to django rest framework's browsable API athttp://localhost:8000/api/
.
djangocms-rest supports OpenAPI 3 schema generation for Django REST framework and type generationfor all endpoints and installed plugins usingdrf-spectacular
.
pip install drf-spectacular
Update yourINSTALLED_APPS
setting:
INSTALLED_APPS= [ ...'drf_spectacular', ...]
Update yoururls.py
settings.
fromdrf_spectacular.viewsimportSpectacularAPIView,SpectacularSwaggerViewurlpatterns= [ ...# OpenAPI schema and documentationpath('api/schema/',SpectacularAPIView.as_view(),name='schema'),path('api/docs/',SpectacularSwaggerView.as_view(url_name='schema'),name='swagger-ui'), ...
Finally, add the schema class to the rest framework settings insettings.py
:
REST_FRAMEWORK= { ...,"DEFAULT_SCHEMA_CLASS":'drf_spectacular.openapi.AutoSchema', ...,}
Test endpoints and check expected response types:http://localhost:8000/api/docs/
Fetch api schema as json/xml:http://localhost:8000/api/schema/
Fur further instructions visit drf_spectacular documentation:https://drf-spectacular.readthedocs.io/en/latest/index.html
{"title":"string","page_title":"string","menu_title":"string","meta_description":"string","redirect":"string","absolute_url":"string","path":"string","is_home":true,"login_required":true,"in_navigation":true,"soft_root":true,"template":"string","xframe_options":"string","limit_visibility_in_menu":false,"language":"string","languages": ["string" ],"is_preview":false,"application_namespace":"string","creation_date":"2025-05-29T07:59:21.301Z","changed_date":"2025-05-29T07:59:21.301Z","children": []}
The following endpoints are available:
If the API is not specifically protected, anyone can access all public content. It's a good idea todisallow/limit public access, or at least implement proper caching.
Public Endpoints | Description |
---|---|
/api/languages/ | Fetch available languages. |
/api/plugins/ | Fetch types for all installed plugins. Used for automatic type checks with frontend frameworks. |
/api/{language}/pages-root/ | Fetch the root page for a given language. |
/api/{language}/pages-tree/ | Fetch the complete page tree of all published documents for a given language. Suitable for smaller projects for automatic navigation generation. For large page sets, use thepages-list endpoint instead. |
/api/{language}/pages-list/ | Fetch a paginated list. Supportslimit andoffset parameters for frontend structure building. |
/api/{language}/pages/{path}/ | Fetch page details by path for a given language. Path and language information is available viapages-list andpages-tree endpoints. |
/api/{language}/placeholders/ {content_type_id}/{object_id}/{slot}/ | Fetch published page content objects for a given language. Parameters available from page detail. |
For all page related endpoints draft content can be fetched, if the user has the permission to viewpreview content.To determine permissionsuser_can_view_page()
from djangocms is used, usually editors withis_staff
are allowed to view draft content.
Private Endpoints | Description |
---|---|
/api/preview/{language}/pages-root | Fetch the latest draft content for the root page. |
/api/preview/{language}/pages-tree | Fetch the page tree including unpublished pages. |
/api/preview/{language}/pages-list | Fetch a paginated list including unpublished pages. |
/api/preview/{language}/pages/{path} | Fetch the latest draft content from a published or unpublished page, including latest unpublished content objects. |
/api/preview/{language}/placeholders/ {content_type_id}/{object_id}/{slot} | Fetch the latest draft content objects for the given language. |
GET CONTENT using
/api/{language}/placeholders/{content_type_id}/{object_id}/{slot}/
{"title":"sub","page_title":"sub","menu_title":"sub","meta_description":"","redirect":null,"in_navigation":true,"soft_root":false,"template":"home.html","xframe_options":"","limit_visibility_in_menu":false,"language":"en","path":"sub","absolute_url":"/sub/","is_home":false,"login_required":false,"languages": ["en" ],"is_preview":false,"application_namespace":null,"creation_date":"2025-02-27T16:49:01.180050Z","changed_date":"2025-02-27T16:49:01.180214Z","placeholders": [ {"content_type_id":5,"object_id":6,"slot":"content" }, {"content_type_id":5,"object_id":6,"slot":"cta" } ]}
Rendered HTML with an optional flag ?html=1
{"slot":"content","label":"Content","language":"en","content": [ {"plugin_type":"TextPlugin","body":"<p>Test Content</p>","json": {"type":"doc","content": [ {"type":"paragraph","attrs": {"textAlign":"left" },"content": [ {"text":"Test Content","type":"text" } ] } ] },"rte":"tiptap" } ],"html":"<p>Test Content</p>"}
Use the provided schema to quickly generate generate clients, SDKs, validators, and more.
TypeScript :https://github.com/hey-api/openapi-ts
Pull requests are welcome. For major changes, please open an issue first to discuss what you wouldlike to change.
About
REST api for django CMS 5
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors4
Uh oh!
There was an error while loading.Please reload this page.