Skip to content

Commit e70c0a1

Browse files
metaforxfsbraun
andauthored
update docs (#26)
* update docs with openapi support and preview endpoints * Refactor API documentation using tables for endpoints * Adjust table formatting * Update README with detailed features and headless CMS info * Update README.md Co-authored-by: Fabian Braun <fsbraun@gmx.de> --------- Co-authored-by: Fabian Braun <fsbraun@gmx.de>
1 parent a39423f commit e70c0a1

File tree

1 file changed

+232
-9
lines changed

1 file changed

+232
-9
lines changed

README.md

Lines changed: 232 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,29 @@
55

66
## What is djangocms-rest?
77

8-
djangocms-rest enables frontend projects to consume django CMS content through a browseable
9-
read-only, REST/JSON API. It is based on the django rest framework (DRF).
8+
djangocms-rest enables frontend projects to consume django CMS content through a browsable
9+
read-only, REST/JSON API. It is based on the django rest framework (DRF) and supports OpenAPI
10+
3 schema generation via drf-spectacular.
11+
12+
**✨ Key Features**
13+
14+
🏢 **Multi-site support** – Supports Django sites<br>
15+
🌍 **Internationalization (i18n)** – Supports available CMS languages<br>
16+
🌲 **Structured page tree** – Fetch the full page tree with metadata<br>
17+
📚 **Paginated page listing** – Retrieve pages as a list with pagination support<br>
18+
👀 **Preview support** – Access draft content using `djangocms-versioning` supporting
19+
permissions for authenticated staff user<br>
20+
🧬 **Typed API schema** – Auto-generate OpenAPI schemas for pages and plugins with
21+
`drf-spectacular`
22+
23+
🧩 **Flexible responses** – Fetch plugin content as JSON or fully rendered HTML
24+
25+
> ⚠️ **Disclaimer**
26+
>
27+
> `djangocms-rest` is under active development. While it is safe to explore and test, using it in
28+
> production is at your own responsibility.
29+
>
30+
> The impact is limited since the API is **read-only** and does not expose any write operations.
1031
1132
## What is headless mode?
1233

@@ -16,14 +37,42 @@ developers to deliver content to any device or platform, such as websites, mobil
1637
devices, using any technology stack. By separating content management from content presentation,
1738
a Headless CMS offers greater flexibility and scalability in delivering content.
1839

40+
Used with `drf-spectacular`, djangocms-rest generates complete OpenAPI schemas for both DRF
41+
endpoints and Django CMS content plugins. This allows seamless, typed integration with
42+
TypeScript-friendly frameworks.
43+
1944
## What are the main benefits of running a CMS in headless mode?
2045

21-
Running a CMS in headless mode offers several benefits, including greater flexibility in delivering
22-
content to multiple platforms and devices through APIs, enabling consistent and efficient
23-
multi-channel experiences. It enhances performance and scalability by allowing frontend and backend
24-
development to progress independently using the best-suited technologies. Additionally, it
25-
streamlines content management, making it easier to update and maintain content across various
26-
applications without needing to alter the underlying infrastructure.
46+
Running a CMS in headless mode offers several advantages, particularly for projects that require
47+
flexibility, scalability, and multi-platform content delivery:
48+
49+
**Benefits of running Django CMS in headless mode:**
50+
51+
- Flexible content delivery to multiple platforms and devices via APIs, enabling consistent
52+
multi-channel experiences.
53+
- Independent development of frontend and backend using best-suited technologies, improving
54+
scalability and team efficiency.
55+
- Improved performance through optimized frontend rendering and decoupled architecture.
56+
- Streamlined content management, allowing editors to update content across applications without
57+
touching the infrastructure.
58+
- Easier integration with modern frameworks (e.g., React, Nuxt, Next.js) and third-party services.
59+
60+
## Are there any drawbacks to using Django CMS in headless mode?
61+
62+
First, consider whether the benefits of a headless system outweigh the cost of running two separate
63+
tech stacks for frontend and backend. For larger projects or when working in teams, having a
64+
separation of concerns across different domains can be a significant advantage. However, for smaller
65+
projects, this is often not the case.
66+
67+
**Limitations and considerations in headless mode:**
68+
69+
- Inline editing and content preview are currently only available in a structured view. (Solutions
70+
are currently being evaluated).
71+
- API-Caching has yet to be addressed properly and should be handled in the frontend app for the
72+
time being.
73+
- Not all features of a standard Django CMS are available through the API (eg. templates and tags).
74+
- The API focuses on fetching plugin content and page structure as JSON data.
75+
- Website rendering is entirely decoupled and must be implemented in the frontend framework.
2776

2877
## Are there js packages for drop-in support of frontend editing in the javascript framework of my choice?
2978

@@ -144,11 +193,185 @@ urlpatterns = [
144193
...
145194
]
146195
```
147-
148196
## Usage
149197

150198
Navigate to django rest framework's browsable API at `http://localhost:8000/api/`.
151199

200+
## OpenAPI 3 Support
201+
202+
djangocms-rest supports OpenAPI 3 schema generation for Django REST framework and type generation
203+
for all endpoints and installed plugins using `drf-spectacular`.
204+
205+
```bash
206+
pip install drf-spectacular
207+
```
208+
209+
Update your `INSTALLED_APPS` setting:
210+
211+
```python
212+
INSTALLED_APPS = [
213+
...
214+
'drf_spectacular',
215+
...
216+
]
217+
```
218+
219+
Update your `urls.py` settings.
220+
221+
```python
222+
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
223+
224+
urlpatterns = [
225+
...
226+
# OpenAPI schema and documentation
227+
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
228+
path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
229+
...
230+
```
231+
232+
Test endpoints and check expected response types: `http://localhost:8000/api/docs/`
233+
234+
Fetch api schema as json/xml: `http://localhost:8000/api/schema/`
235+
236+
Fur further instructions visit drf_spectacular documentation:
237+
https://drf-spectacular.readthedocs.io/en/latest/index.html
238+
239+
### Response schema as JSON for a page object in a list
240+
241+
```json
242+
{
243+
"title": "string",
244+
"page_title": "string",
245+
"menu_title": "string",
246+
"meta_description": "string",
247+
"redirect": "string",
248+
"absolute_url": "string",
249+
"path": "string",
250+
"is_home": true,
251+
"in_navigation": true,
252+
"soft_root": true,
253+
"template": "string",
254+
"xframe_options": "string",
255+
"limit_visibility_in_menu": true,
256+
"language": "string",
257+
"languages": [
258+
"string"
259+
],
260+
"children": []
261+
}
262+
```
263+
264+
## API Endpoints
265+
266+
The following endpoints are available:
267+
268+
### Public API
269+
270+
If the API is not specifically protected, anyone can access all public content. It's a good idea to
271+
disallow/limit public access, or at least implement proper caching.
272+
273+
| Public Endpoints | Description |
274+
|:----------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
275+
| `/api/languages/` | Fetch available languages. |
276+
| `/api/plugins/` | Fetch types for all installed plugins. Used for automatic type checks with frontend frameworks. |
277+
| `/api/{language}/pages-root/` | Fetch the root page for a given language. |
278+
| `/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. |
279+
| `/api/{language}/pages-list/` | Fetch a paginated list. Supports `limit` and `offset` parameters for frontend structure building. |
280+
| `/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. |
281+
| `/api/{language}/placeholders/`<br/>`{content_type_id}/{object_id}/{slot}/` | Fetch published page content objects for a given language. Parameters available from page detail. |
282+
283+
### Private API (Preview)
284+
285+
For all page related endpoints draft content can be fetched, if the user has the permission to view
286+
preview content.
287+
To determine permissions `user_can_view_page()` from djangocms is used, usually editors with
288+
`is_staff` are allowed to view draft content.
289+
290+
| Private Endpoints | Description |
291+
|:-----------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|
292+
| `/api/preview/{language}/pages-root` | Fetch the latest draft content for the root page. |
293+
| `/api/preview/{language}/pages-tree` | Fetch the page tree including unpublished pages. |
294+
| `/api/preview/{language}/pages-list` | Fetch a paginated list including unpublished pages. |
295+
| `/api/preview/{language}/pages/{path}` | Fetch the latest draft content from a published or unpublished page, including latest unpublished content objects. |
296+
| `/api/preview/{language}/placeholders/`<br/>`{content_type_id}/{object_id}/{slot}` | Fetch the latest draft content objects for the given language. |
297+
| |
298+
299+
### Sample API-Response: api/{en}/pages/{sub}/
300+
301+
```json
302+
{
303+
"title": "sub",
304+
"page_title": "sub",
305+
"menu_title": "sub",
306+
"meta_description": "",
307+
"redirect": null,
308+
"in_navigation": true,
309+
"soft_root": false,
310+
"template": "INHERIT",
311+
"xframe_options": 0,
312+
"limit_visibility_in_menu": null,
313+
"language": "en",
314+
"path": "sub",
315+
"absolute_url": "/sub/",
316+
"is_home": false,
317+
"languages": [
318+
"en"
319+
],
320+
"is_preview": false,
321+
"creation_date": "2025-02-26T21:22:16.844637Z",
322+
"changed_date": "2025-02-26T21:22:16.856326Z",
323+
// GET CONTENT using `/api/{language}/placeholders/{content_type_id}/{object_id}/{slot}/`
324+
"placeholders": [
325+
{
326+
"content_type_id": 5,
327+
"object_id": 5,
328+
"slot": "content"
329+
}
330+
]
331+
}
332+
```
333+
334+
### Sample API-Response: api/{en}/placeholders/{5}/{5}/{content}/[?html=1]
335+
336+
```json
337+
{
338+
"slot": "content",
339+
"label": "Content",
340+
"language": "en",
341+
"content": [
342+
{
343+
"plugin_type": "TextPlugin",
344+
"body": "<p>Test Content</p>",
345+
"json": {
346+
"type": "doc",
347+
"content": [
348+
{
349+
"type": "paragraph",
350+
"attrs": {
351+
"textAlign": "left"
352+
},
353+
"content": [
354+
{
355+
"text": "Test Content",
356+
"type": "text"
357+
}
358+
]
359+
}
360+
]
361+
},
362+
"rte": "tiptap"
363+
}
364+
],
365+
"html": "<p>Test Content</p>"
366+
//Rendered HTML when uins ?html=1
367+
}
368+
```
369+
370+
### OpenAPI Type Generation
371+
372+
Use the provided schema to quickly generate generate clients, SDKs, validators, and more.
373+
374+
**TypeScript** : https://github.com/hey-api/openapi-ts
152375
## Contributing
153376

154377
Pull requests are welcome. For major changes, please open an issue first to discuss what you would

0 commit comments

Comments
 (0)