Skip to content

Commit 8e3ec95

Browse files
metaforxfsbraunsourcery-ai[bot]
authored
docs: Update README features and documentation links (#88)
* docs: Update README features and documentation links * Update README.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Update README.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Update README.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * fix: Update API URL :8080 to :8000 * docs: Clarify usage of `rest_framework` in README.md * Update README.md --------- Co-authored-by: Fabian Braun <fsbraun@gmx.de> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
1 parent 0387baa commit 8e3ec95

File tree

1 file changed

+103
-206
lines changed

1 file changed

+103
-206
lines changed

README.md

Lines changed: 103 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,84 @@
44
[![django CMS versions](https://img.shields.io/pypi/frameworkversions/django-cms/djangocms-rest.svg?style=flat-square)](https://pypi.python.org/pypi/djangocms-rest)
55
[![License](https://img.shields.io/github/license/django-cms/djangocms-rest.svg?style=flat-square)](https://pypi.python.org/pypi/djangocms-rest)
66

7-
# django CMS Headless Mode
7+
# djangocms-rest
88

9-
## What is djangocms-rest?
9+
djangocms-rest enables frontend projects to consume django CMS content through a browsable,
10+
read-only REST/JSON API. Built on Django REST Framework (DRF) with OpenAPI 3 schema generation
11+
via drf-spectacular.
1012

11-
djangocms-rest enables frontend projects to consume django CMS content through a browsable
12-
read-only, REST/JSON API. It is based on the django rest framework (DRF) and supports OpenAPI
13-
3 schema generation via drf-spectacular.
13+
## Key Features
1414

15-
**✨ Key Features**
15+
- **Easy integration** – Integrates effortlessly into existing Django CMS projects
16+
- **REST API** – DRF-based API exposing Django CMS content for SPAs, static sites, and mobile apps
17+
- **Typed Endpoints** – Auto-generate OpenAPI schemas for page data and plugin content
18+
- **Plugin Serialization** – Basic support for all CMS plugins, easily extendable for custom needs
19+
- **Multi-Site Support** – Serve multiple websites from a single instance with isolated API responses
20+
- **Multi-language Content** – Use the robust i18n integration of Django CMS in your frontend
21+
- **Preview & Draft Access** – Fetch unpublished or draft content in your frontend for editing previews
22+
- **Permissions & Authentication** – Uses DRF and Django permissions for secure access control
23+
- **Menus & Breadcrumbs** – Exposes the built-in navigation handlers from Django CMS
24+
- **Caching & Performance** – Works with Django cache backends like Redis and Memcached
1625

17-
💫 **Django CMS 4 and 5 Support** – Including latest version support (5.0)<br>
18-
🏢 **Multi-site support** – Supports Django sites<br>
19-
🌍 **Internationalization (i18n)** – Supports available CMS languages<br>
20-
🌲 **Structured page tree** – Fetch the full page tree with metadata<br>
21-
📚 **Paginated page listing** – Retrieve pages as a list with pagination support<br>
22-
🔄 **Built-in caching** - Uses django cache backend for placeholder serialization/rendering<br>
23-
👀 **Preview support** – Access draft content using `djangocms-versioning` supporting
24-
permissions for authenticated staff user<br>
25-
🧬 **Typed API schema** – Auto-generate OpenAPI schemas for pages and plugins with
26-
`drf-spectacular`
26+
## Requirements
27+
28+
- Python >= 3.10, < 3.14
29+
- Django >= 4.2, < 6.1
30+
- Django CMS >= 4.1, < 5.1
31+
32+
## Installation
33+
34+
Install using pip:
35+
36+
```bash
37+
pip install djangocms-rest
38+
```
39+
40+
Update your `INSTALLED_APPS` setting:
41+
42+
```python
43+
INSTALLED_APPS = [
44+
...
45+
"djangocms_rest",
46+
...
47+
]
48+
```
49+
50+
> `rest_framework` is installed as a dependency. Add it to `INSTALLED_APPS` if you want to use the browsable API UI or create additional DRF endpoints beyond djangocms-rest.
51+
52+
Add the API endpoints to your project's `urls.py`:
53+
54+
```python
55+
from django.urls import path, include
56+
57+
urlpatterns = [
58+
...
59+
path('api/', include('djangocms_rest.urls')),
60+
...
61+
]
62+
```
63+
> Using `api/cms/` as the path helps separate djangocms-rest endpoints in API documentation and frontend implementation.
64+
65+
66+
### Usage
2767

28-
🧩 **Flexible responses** – Fetch plugin content as JSON or fully rendered HTML
68+
Make sure you have existing pages. If `rest_framework` is in `INSTALLED_APPS`, you can navigate to Django REST Framework's browsable API at `http://localhost:8000/api/`.
2969

30-
> ⚠️ **Note**
31-
>
32-
> `djangocms-rest` is under active development. Since the API is read-only, it's safe to explore
33-
> without risk of unintended data changes.
70+
## Documentation
3471

35-
## What is headless mode?
72+
- **Getting Started** – Quick start guide and installation instructions
73+
- **OpenAPI Support** – Schema generation and API documentation setup
74+
- **How-to Guides** – Multi-site configuration, plugin creation, and serialization
75+
- **API Reference** – Complete endpoint documentation
76+
77+
See the [full documentation](https://djangocms-rest.readthedocs.io/en/latest/index.html) for details.
78+
79+
## Headless Mode
80+
81+
### What is headless mode?
3682

3783
A Headless CMS (Content Management System) is a backend-only content management system that provides
38-
content through APIs, making it decoupled from the front-end presentation layer. This allows
84+
content through APIs, making it decoupled from the frontend presentation layer. This allows
3985
developers to deliver content to any device or platform, such as websites, mobile apps, or IoT
4086
devices, using any technology stack. By separating content management from content presentation,
4187
a Headless CMS offers greater flexibility and scalability in delivering content.
@@ -44,43 +90,31 @@ Used with `drf-spectacular`, djangocms-rest generates complete OpenAPI schemas f
4490
endpoints and Django CMS content plugins. This allows seamless, typed integration with
4591
TypeScript-friendly frameworks.
4692

47-
## What are the main benefits of running a CMS in headless mode?
48-
49-
Running a CMS in headless mode offers several advantages, particularly for projects that require
50-
flexibility, scalability, and multi-platform content delivery:
93+
### Benefits
5194

52-
**Benefits of running Django CMS in headless mode:**
95+
- Decouple frontend and backend development—use any frontend framework (React, Vue, Angular, Next.js, Nuxt, SvelteKit, Remix, Astro, etc.)
96+
- Serve content to multiple platforms (web, mobile, IoT) via REST/JSON APIs
97+
- Improved performance through optimized frontend rendering
98+
- Content updates propagate across all platforms without frontend deployments
99+
- Easier integration with modern frameworks and third-party services
53100

54-
- Flexible content delivery to multiple platforms and devices via APIs, enabling consistent
55-
multi-channel experiences.
56-
- Independent development of frontend and backend using best-suited technologies, improving
57-
scalability and team efficiency.
58-
- Improved performance through optimized frontend rendering and decoupled architecture.
59-
- Streamlined content management, allowing editors to update content across applications without
60-
touching the infrastructure.
61-
- Easier integration with modern frameworks (e.g., React, Nuxt, Next.js) and third-party services.
62-
63-
## Are there any drawbacks to using Django CMS in headless mode?
64-
65-
First, consider whether the benefits of a headless system outweigh the cost of running two separate
66-
tech stacks for frontend and backend. For larger projects or when working in teams, having a
67-
separation of concerns across different domains can be a significant advantage. However, for smaller
68-
projects, this is often not the case.
69-
70-
**Limitations and considerations in headless mode:**
101+
### Considerations
71102

72103
- Inline editing and content preview are available as JSON views on both edit and preview mode. Turn
73104
JSON rendering on and off using the `REST_JSON_RENDERING` setting.
74-
- The API focuses on fetching plugin content and page structure as JSON data.
105+
- Use `Structure Mode` in CMS to directly edit content in the frontend when the decoupled view is embedded as an iframe.
106+
- The API focuses on fetching plugin content and page structure as JSON data. Apphook logic must be
107+
implemented using custom logic.
75108
- Website rendering is entirely decoupled and must be implemented in the frontend framework.
76-
- Not (yet) all features of a standard Django CMS are available through the API (eg. Menu).
77109

78-
## Are there js packages for drop-in support of frontend editing in the javascript framework of my choice?
110+
## FAQ
111+
112+
### Are there JavaScript packages for drop-in support of frontend editing in the JavaScript framework of my choice?
79113

80114
The good news first: django CMS headless mode is fully backend supported and works independently
81115
of the javascript framework. It is fully compatible with the javascript framework of your choosing.
82116

83-
## How can I implement a plugin for headless mode?
117+
### How can I implement a plugin for headless mode?
84118

85119
It's pretty much the same as for a traditional django CMS project, see
86120
[here for instructions on how to create django CMS plugins](https://docs.django-cms.org/en/latest/how_to/09-custom_plugins.html).
@@ -138,14 +172,14 @@ class CustomHeadingPluginModel(CMSPlugin):
138172
```
139173

140174

141-
## Do default plugins support headless mode out of the box?
175+
### Do default plugins support headless mode out of the box?
142176

143177
Yes, djangocms-rest provides out of the box support for any and all django CMS plugins whose content
144178
can be serialized.
145179

146180
Custom DRF serializers can be declared for custom plugins by setting its `serializer_class` property.
147181

148-
## Does the TextPlugin (Rich Text Editor, RTE) provide a json representation of the rich text?
182+
### Does the TextPlugin (Rich Text Editor, RTE) provide a JSON representation of the rich text?
149183

150184
Yes, djangocms-text has both HTML blob and structured JSON support for rich text.
151185

@@ -155,160 +189,39 @@ If resolution fails dynamic objects are returned in the form of `<app-name>.<obj
155189
`cms.page:2`. The frontend can then use this to resolve the object and create the appropriate URLs
156190
to the object's frontend representation.
157191

158-
## I don't need pages, I just have a fixed number of content areas in my frontend application for which I need CMS support.
192+
### I don't need pages, I just have a fixed number of content areas in my frontend application for which I need CMS support.
159193

160194
Absolutely, you can use the djangocms-aliases package. It allows you to define custom _placeholders_
161195
that are not linked to any pages. djangocms-rest will then make a list of those aliases and their
162196
content available via the REST API.
163197

164-
## Requirements
165-
166-
- Python
167-
- Django
168-
- Django CMS
169-
170-
## Installation
171-
172-
Install using pip:
173-
174-
```bash
175-
pip install git+https://github.com/django-cms/djangocms-rest@main
176-
```
177-
178-
Update your `INSTALLED_APPS` setting:
179-
180-
```python
181-
INSTALLED_APPS = [
182-
...
183-
'djangocms_rest',
184-
'rest_framework',
185-
...
186-
]
187-
```
188-
189-
```python
190-
# Enabled Caching
191-
CONTENT_CACHE_DURATION = 60 # Overwrites default from django CMS
192-
CACHES = {
193-
'default': {
194-
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', # use redis/memcached etc.
195-
'LOCATION': 'unique-snowflake',
196-
'TIMEOUT': CONTENT_CACHE_DURATION, # change accordingly
197-
}
198-
}
199-
```
200-
201-
Add the API endpoints to your project's `urls.py`:
202-
203-
```python
204-
from django.urls import path, include
205-
206-
urlpatterns = [
207-
...
208-
path('api/', include('djangocms_rest.urls')),
209-
...
210-
]
211-
```
212-
## Usage
213-
214-
Navigate to django rest framework's browsable API at `http://localhost:8000/api/`.
215-
216198
## OpenAPI 3 Support
217199

218200
djangocms-rest supports OpenAPI 3 schema generation for Django REST framework and type generation
219201
for all endpoints and installed plugins using `drf-spectacular`.
220202

221-
```bash
222-
pip install drf-spectacular
223-
```
224-
225-
Update your `INSTALLED_APPS` setting:
226-
227-
```python
228-
INSTALLED_APPS = [
229-
...
230-
'drf_spectacular',
231-
...
232-
]
233-
```
234-
235-
Update your `urls.py` settings.
236-
237-
```python
238-
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
239-
240-
urlpatterns = [
241-
...
242-
# OpenAPI schema and documentation
243-
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
244-
path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
245-
...
246-
```
247-
248-
Finally, add the schema class to the rest framework settings in `settings.py`:
249-
```python
250-
REST_FRAMEWORK = {
251-
...,
252-
"DEFAULT_SCHEMA_CLASS": 'drf_spectacular.openapi.AutoSchema',
253-
...,
254-
}
255-
```
256-
257-
Test endpoints and check expected response types: `http://localhost:8000/api/docs/`
258-
259-
Fetch api schema as json/xml: `http://localhost:8000/api/schema/`
260-
261-
Fur further instructions visit drf_spectacular documentation:
262-
https://drf-spectacular.readthedocs.io/en/latest/index.html
263-
264-
### Response schema as JSON for a page object in a list
265-
266-
```json
267-
{
268-
"title": "string",
269-
"page_title": "string",
270-
"menu_title": "string",
271-
"meta_description": "string",
272-
"redirect": "string",
273-
"absolute_url": "string",
274-
"path": "string",
275-
"is_home": true,
276-
"login_required": true,
277-
"in_navigation": true,
278-
"soft_root": true,
279-
"template": "string",
280-
"xframe_options": "string",
281-
"limit_visibility_in_menu": false,
282-
"language": "string",
283-
"languages": [
284-
"string"
285-
],
286-
"is_preview": false,
287-
"application_namespace": "string",
288-
"creation_date": "2025-05-29T07:59:21.301Z",
289-
"changed_date": "2025-05-29T07:59:21.301Z",
290-
"children": []
291-
}
292-
```
293-
294203
## API Endpoints
295204

296205
The following endpoints are available:
297206

298207
### Public API
299208

300-
If the API is not specifically protected, anyone can access all public content. It's a good idea to
301-
disallow/limit public access, or at least implement proper caching.
302-
303-
| Public Endpoints | Description |
304-
|:----------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
305-
| `/api/languages/` | Fetch available languages. |
306-
| `/api/plugins/` | Fetch types for all installed plugins. Used for automatic type checks with frontend frameworks. |
307-
| `/api/{language}/pages/` | Fetch the root page for a given language. |
308-
| `/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 the `pages-list` endpoint instead. |
309-
| `/api/{language}/pages-list/` | Fetch a paginated list. Supports `limit` and `offset` parameters for frontend structure building. |
310-
| `/api/{language}/pages/{path}/` | Fetch page details by path for a given language. Path and language information is available via `pages-list` and `pages-tree` endpoints. |
311-
| `/api/{language}/placeholders/`<br/>`{content_type_id}/{object_id}/{slot}/` | Fetch published page content objects for a given language. Parameters available from page detail. |
209+
| Endpoints | Description |
210+
|:----------|:------------|
211+
| `/api/languages/` | Fetch available languages for the site |
212+
| `/api/plugins/` | Fetch plugin type definitions for frontend type checks |
213+
| `/api/{language}/pages/` | Fetch the root page for a given language |
214+
| `/api/{language}/pages-tree/` | Fetch complete page tree (suitable for smaller projects) |
215+
| `/api/{language}/pages-list/` | Fetch paginated page list with `limit` and `offset` support |
216+
| `/api/{language}/pages/{path}/` | Fetch page details by path |
217+
| `/api/{language}/page_search/` | Search pages by query term |
218+
| `/api/{language}/placeholders/{content_type_id}/{object_id}/{slot}/` | Fetch placeholder content (supports `?html=1` for rendered HTML) |
219+
| `/api/{language}/menu/...` | Fetch menu navigation (supports optional `{from_level}/{to_level}/{extra_inactive}/{extra_active}`, `{root_id}`, and `{path}` parameters) |
220+
| `/api/{language}/submenu/...` | Fetch submenu navigation (supports optional `{levels}`, `{root_level}`, `{nephews}`, and `{path}` parameters) |
221+
| `/api/{language}/breadcrumbs/...` | Fetch breadcrumb navigation (supports optional `{start_level}` and `{path}` parameters) |
222+
223+
> **Documentation**
224+
> For complete endpoint documentation, request/response schemas, and authentication details, see the [API Reference](https://djangocms-rest.readthedocs.io/en/latest/reference/index.html).
312225
313226
### Private API (Preview)
314227

@@ -375,23 +288,7 @@ Just add the `?preview` GET parameter to the above page, page-tree, or page-list
375288
{
376289
"plugin_type": "TextPlugin",
377290
"body": "<p>Test Content</p>",
378-
"json": {
379-
"type": "doc",
380-
"content": [
381-
{
382-
"type": "paragraph",
383-
"attrs": {
384-
"textAlign": "left"
385-
},
386-
"content": [
387-
{
388-
"text": "Test Content",
389-
"type": "text"
390-
}
391-
]
392-
}
393-
]
394-
},
291+
"json": { ... },
395292
"rte": "tiptap"
396293
}
397294
],

0 commit comments

Comments
 (0)