Skip to content

Commit 18b2937

Browse files
authored
Merge pull request #83 from Old6Man6/add-api-examples
Add CRUD API example and update documentation
2 parents 957f3c5 + 3cb4ffd commit 18b2937

File tree

5 files changed

+258
-0
lines changed

5 files changed

+258
-0
lines changed

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,21 @@ examples/static-collected
3030

3131
# OS-specific
3232
.DS_Store
33+
34+
# Chromium / Electron cache
35+
.org.chromium.*
36+
Cache/
37+
CachedData/
38+
CachedProfilesData/
39+
Code Cache/
40+
Crashpad/
41+
DIPS*
42+
Dawn*
43+
GPUCache/
44+
Local Storage/
45+
Preferences
46+
Trust Tokens*
47+
User/
48+
code.lock
49+
languagepacks.json
50+
machineid

docs/apis.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ This gives you an easy way to define your API endpoints:
2828
See the `Django Ninja documentation <https://django-ninja.dev/>`_ for more details of
2929
how to use the ``NinjaAPI`` instance at ``@app.api``.
3030

31+
See also
32+
========
33+
For CRUD examples, see:
34+
35+
- :doc:`howto_api` — a complete CRUD Todo API
3136

3237
Other Ninja features
3338
====================

docs/howto_api.rst

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
Build a Simple API(CRUD)
2+
=================
3+
4+
This example demonstrates how to build a simple CRUD (Create, Read, Update, Delete)
5+
API using NanoDjango’s built-in `Django Ninja <https://django-ninja.dev/>`_ support.
6+
7+
We implement a minimal in-memory "Todo" database with endpoints for creating,
8+
listing, retrieving, updating, and deleting items.
9+
10+
Example code
11+
------------
12+
13+
.. code-block:: python
14+
15+
# hello_api.py
16+
from nanodjango.app import Django
17+
18+
# Initialise NanoDjango
19+
app = Django()
20+
21+
# Fake in-memory database
22+
todos = {}
23+
24+
# ---- Schema for Todo ----
25+
class Todo(app.ninja.Schema):
26+
id: int | None = None # Auto-assigned
27+
title: str
28+
done: bool = False
29+
30+
# ---- CREATE ----
31+
@app.api.post("/todos")
32+
def create_todo(request, payload: Todo):
33+
todo_id = len(todos) + 1
34+
todo = Todo(id=todo_id, title=payload.title, done=payload.done)
35+
todos[todo_id] = todo.dict()
36+
return todos[todo_id]
37+
38+
# ---- READ ALL ----
39+
@app.api.get("/todos")
40+
def list_todos(request):
41+
return list(todos.values())
42+
43+
# ---- READ ONE ----
44+
@app.api.get("/todos/{todo_id}")
45+
def get_todo(request, todo_id: int):
46+
todo = todos.get(todo_id)
47+
if not todo:
48+
return {"error": "Todo not found"}, 404
49+
return todo
50+
51+
# ---- UPDATE ----
52+
@app.api.put("/todos/{todo_id}")
53+
def update_todo(request, todo_id: int, payload: Todo):
54+
if todo_id not in todos:
55+
return {"error": "Todo not found"}, 404
56+
updated = todos[todo_id]
57+
updated["title"] = payload.title
58+
updated["done"] = payload.done
59+
todos[todo_id] = updated
60+
return updated
61+
62+
# ---- DELETE ----
63+
@app.api.delete("/todos/{todo_id}")
64+
def delete_todo(request, todo_id: int):
65+
if todo_id not in todos:
66+
return {"error": "Todo not found"}, 404
67+
del todos[todo_id]
68+
return {"message": "Deleted"}
69+
70+
71+
Running the app
72+
---------------
73+
74+
Run the API using :
75+
76+
.. code-block:: bash
77+
78+
cd /examples
79+
python -m nanodjango run hello_api.py
80+
81+
82+
Endpoints
83+
---------
84+
85+
All endpoints are available under ``/api/``:
86+
87+
**1. Create a Todo (POST)**
88+
89+
- URL: ``/api/todos``
90+
- Body: JSON object with ``title`` and optional ``done``
91+
92+
.. code-block:: bash
93+
94+
curl -X POST http://127.0.0.1:8000/api/todos \
95+
-H "Content-Type: application/json" \
96+
-d '{"title": "Learn NanoDjango", "done": false}'
97+
98+
Response:
99+
100+
.. code-block:: json
101+
102+
{"id": 1, "title": "Learn NanoDjango", "done": false}
103+
104+
105+
**2. List all Todos (GET)**
106+
107+
- URL: ``/api/todos``
108+
109+
.. code-block:: bash
110+
111+
curl http://127.0.0.1:8000/api/todos
112+
113+
Response:
114+
115+
.. code-block:: json
116+
117+
[{"id": 1, "title": "Learn NanoDjango", "done": false}]
118+
119+
120+
**3. Get a Todo by ID (GET)**
121+
122+
- URL: ``/api/todos/{id}``
123+
124+
.. code-block:: bash
125+
126+
curl http://127.0.0.1:8000/api/todos/1
127+
128+
Response:
129+
130+
.. code-block:: json
131+
132+
{"id": 1, "title": "Learn NanoDjango", "done": false}
133+
134+
135+
**4. Update a Todo (PUT)**
136+
137+
- URL: ``/api/todos/{id}``
138+
- Body: JSON object with updated ``title`` and ``done``
139+
140+
.. code-block:: bash
141+
142+
curl -X PUT http://127.0.0.1:8000/api/todos/1 \
143+
-H "Content-Type: application/json" \
144+
-d '{"title": "Learn N@n0Dj@n60 deeply", "done": true}'
145+
146+
Response:
147+
148+
.. code-block:: json
149+
150+
{"id": 1, "title": "Learn N@n0Dj@n60 deeply", "done": true}
151+
152+
153+
**5. Delete a Todo (DELETE)**
154+
155+
- URL: ``/api/todos/{id}``
156+
157+
.. code-block:: bash
158+
159+
curl -X DELETE http://127.0.0.1:8000/api/todos/1
160+
161+
Response:
162+
163+
.. code-block:: json
164+
165+
{"message": "Deleted"}
166+
167+
168+
Notes
169+
-----
170+
171+
- ``@app.api`` is an instance of ``NinjaAPI`` automatically mounted at ``/api/``.
172+
- ``app.ninja.Schema`` is used to define input validation and output schema.
173+
- This example stores data in an in-memory dictionary, which resets on restart.
174+
- For persistence, you can later integrate with Django ORM models.

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Perfect for experiments, prototypes, tutorials, and small applications.
1919
templates
2020
template_tags
2121
apis
22+
howto_api
2223
admin
2324
integrations
2425
convert

examples/hello_api.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# hello_crud.py
2+
from nanodjango.app import Django
3+
4+
# Initialise NanoDjango
5+
app = Django()
6+
7+
# Fake in-memory database
8+
todos = {}
9+
10+
11+
# ---- Schema for Todo ----
12+
class Todo(app.ninja.Schema):
13+
id: int | None = None # Auto-assigned
14+
title: str
15+
done: bool = False
16+
17+
18+
# ---- CREATE ----
19+
@app.api.post("/todos")
20+
def create_todo(request, payload: Todo):
21+
todo_id = len(todos) + 1
22+
todo = Todo(id=todo_id, title=payload.title, done=payload.done)
23+
todos[todo_id] = todo.dict()
24+
return todos[todo_id]
25+
26+
27+
# ---- READ ALL ----
28+
@app.api.get("/todos")
29+
def list_todos(request):
30+
return list(todos.values())
31+
32+
33+
# ---- READ ONE ----
34+
@app.api.get("/todos/{todo_id}")
35+
def get_todo(request, todo_id: int):
36+
todo = todos.get(todo_id)
37+
if not todo:
38+
return {"error": "Todo not found"}, 404
39+
return todo
40+
41+
42+
# ---- UPDATE ----
43+
@app.api.put("/todos/{todo_id}")
44+
def update_todo(request, todo_id: int, payload: Todo):
45+
if todo_id not in todos:
46+
return {"error": "Todo not found"}, 404
47+
updated = todos[todo_id]
48+
updated["title"] = payload.title
49+
updated["done"] = payload.done
50+
todos[todo_id] = updated
51+
return updated
52+
53+
54+
# ---- DELETE ----
55+
@app.api.delete("/todos/{todo_id}")
56+
def delete_todo(request, todo_id: int):
57+
if todo_id not in todos:
58+
return {"error": "Todo not found"}, 404
59+
del todos[todo_id]
60+
return {"message": "Deleted"}

0 commit comments

Comments
 (0)