A simple Django-based Content Management System (CMS) project.
- Python 3.12
- Django
venvfor virtual environment managementpipandrequirements/base.txtfor dependency management
git clone https://github.com/Miladkhoshdel/django-cms
cd django-cmsOn macOS/Linux:
python3 -m venv .venv
source .venv/bin/activateOn Windows:
python -m venv .venv
.venv\Scripts\activatepython -m pip install --upgrade pip
pip install -r requirements/base.txtpython manage.py migratepython manage.py loaddata initial_settingspython manage.py createsuperuserpython manage.py runserverThe app will be available at http://127.0.0.1:8000/.
The admin panel is available at http://127.0.0.1:8000/panel/.
Public blog pages render only published posts.
GET http://127.0.0.1:8000/posts/
GET http://127.0.0.1:8000/posts/<slug>/
POST http://127.0.0.1:8000/api/token/
Send a POST request to the token endpoint with your credentials:
{
"username": "<user>",
"password": "<password>"
}Sample Response:
{
"refresh": "<refresh_token>",
"access": "<access_token>"
}POST http://127.0.0.1:8000/api/token/verify/
Send a POST request to the verify endpoint with your token:
{
"token": "<access_token>"
}Sample Error Response (Expired Token):
{
"detail": "Token is expired",
"code": "token_not_valid"
}GET http://127.0.0.1:8000/api/v1/core/settings/
Sample Response:
{
"success": true,
"data": {
"site_title": "Django CMS",
"site_description": "Simple Django CMS",
"site_keywords": "Django, CMS, Python",
"site_author": "Your Name",
"site_logo_path": "/static/images/logo.png"
}
}GET http://127.0.0.1:8000/api/v1/core/settings/<key>/
Sample Response:
{
"success": true,
"data": {
"key": "site_keywords",
"value": "Django, CMS, Python"
}
}Blog API endpoints are available under /api/v1/blog/ and require a JWT access token:
Authorization: Bearer <access_token>POST http://127.0.0.1:8000/api/v1/blog/posts/
Sample Request:
curl -X POST http://127.0.0.1:8000/api/v1/blog/posts/ \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"title": "First weblog post",
"excerpt": "Short summary",
"content": "Full blog post content here.",
"status": "published"
}'Sample Response:
{
"id": 1,
"title": "First weblog post",
"slug": "first-weblog-post",
"excerpt": "Short summary",
"content": "Full blog post content here.",
"status": "published",
"published_at": "2026-05-07T14:55:00Z",
"author": "admin",
"created_at": "2026-05-07T14:55:00Z",
"updated_at": "2026-05-07T14:55:00Z"
}GET http://127.0.0.1:8000/api/v1/blog/posts/
Sample Request:
curl http://127.0.0.1:8000/api/v1/blog/posts/ \
-H "Authorization: Bearer <access_token>"Sample Response:
[
{
"id": 1,
"title": "First weblog post",
"slug": "first-weblog-post",
"excerpt": "Short summary",
"content": "Full blog post content here.",
"status": "published",
"published_at": "2026-05-07T14:55:00Z",
"author": "admin",
"created_at": "2026-05-07T14:55:00Z",
"updated_at": "2026-05-07T14:55:00Z"
}
]GET http://127.0.0.1:8000/api/v1/blog/posts/?status=published
Sample Request:
curl "http://127.0.0.1:8000/api/v1/blog/posts/?status=published" \
-H "Authorization: Bearer <access_token>"Sample Response:
[
{
"id": 1,
"title": "First weblog post",
"slug": "first-weblog-post",
"excerpt": "Short summary",
"content": "Full blog post content here.",
"status": "published",
"published_at": "2026-05-07T14:55:00Z",
"author": "admin",
"created_at": "2026-05-07T14:55:00Z",
"updated_at": "2026-05-07T14:55:00Z"
}
]GET http://127.0.0.1:8000/api/v1/blog/posts/<slug>/
Sample Request:
curl http://127.0.0.1:8000/api/v1/blog/posts/first-weblog-post/ \
-H "Authorization: Bearer <access_token>"Sample Response:
{
"id": 1,
"title": "First weblog post",
"slug": "first-weblog-post",
"excerpt": "Short summary",
"content": "Full blog post content here.",
"status": "published",
"published_at": "2026-05-07T14:55:00Z",
"author": "admin",
"created_at": "2026-05-07T14:55:00Z",
"updated_at": "2026-05-07T14:55:00Z"
}PATCH http://127.0.0.1:8000/api/v1/blog/posts/<slug>/
Sample Request:
curl -X PATCH http://127.0.0.1:8000/api/v1/blog/posts/first-weblog-post/ \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"status":"draft"}'Sample Response:
{
"id": 1,
"title": "First weblog post",
"slug": "first-weblog-post",
"excerpt": "Short summary",
"content": "Full blog post content here.",
"status": "draft",
"published_at": "2026-05-07T14:55:00Z",
"author": "admin",
"created_at": "2026-05-07T14:55:00Z",
"updated_at": "2026-05-07T15:10:00Z"
}DELETE http://127.0.0.1:8000/api/v1/blog/posts/<slug>/
Sample Request:
curl -X DELETE http://127.0.0.1:8000/api/v1/blog/posts/first-weblog-post/ \
-H "Authorization: Bearer <access_token>"Sample Response:
HTTP/1.1 204 No Content