Django Ninja - ein asynchrones Restframework für Django
https://www.youtube.com/watch?v=S4nUhruExwA aktuell 8:00
Installation
In die requirements.in wird eingetragen:
django-ninja
pip-compile requirements.in
pip-sync requirements-dev.txt requirements.txt
Vorarbeiten
Eine neue App namens tickets erstellen und ein Model anlegen.
python manage.py startapp tickets
In die neu erstellt App legen wir unter models.py ein Model für ein Ticket an.
from django.db import models
from event_manager.mixins import DateMixin
class Ticket(DateMixin):
class Status(models.TextChoices):
"new", "new"
status = models.CharField(max_length=20, choices=Status.choices)
und führen wir gewohnt makemirations und migrate aus.
Unter event_manager/tickets legen wir nun eine Datei api.py, in der der Quellcode für die Ninja-API liegen wird.
Wir legen auch noch eine urls.py an.
Unser neues tickets-verzeichnis sieht nun so aus:
.
├── admin.py
├── api.py
├── apps.py
├── __init__.py
├── migrations
├── models.py
├── tests.py
├── urls.py
└── views.py
Legen wir zuerst unter event_manager/event_manager/urls.py die Verknüpfung
zu unserer Api fest, damit die API-Endpunkte auch gefunden werden können.
urlpatterns = [
...
path("api/tickets/", include("tickets.urls")),
...
]
in die event_manager/tickets/urls.py tragen wir folgendes ein:
from django.urls import path
from .api import api
urlpatters = [
path("", api.urls),
]
Die tatsächlichen Routen erzeugt Django-Ninja automatisch für uns.
Der erste Endpunkt
Unter event_manager/tickets/api.py tragen wir folgenden Code ein:
from ninja import NinjaAPI
api = NinjaAPI()
@api.get("/")
def home(request):
return "Hello World"
Hier haben wir einen Endpunkt erstellt, der jetzt unter
http://127.0.0.1:8000/api/tickets/ erreichbar ist. Die URL hat Django-Ninja für uns selbst erstellt, auch um die Serialisierung mussten wir uns nicht kümmern.
Ticket erstellen
Um ein Ticket zu erstellen, benötigen wir das Django ORM. Um die
Eingangsdaten allerdings erstmal zu validieren, legen wir ein Schema an
from ninja import ModelSchema, Schema
from .models import Ticket
class MessageIn(Schema):
title: str
msg: str
Und definieren in api.py den entsprechenden Endpunkt.
from .schema import MessageIn
@api.post("msg")
def msg(request, data: MessageIn):
return data
jetzt können wir das zum Beispiel mit curl testen
curl http://127.0.0.1:8000/api/tickets/msg -d '{"title":"wow", "msg":"hi
there!"}' -X POST
Das hat geklappt! Jetzt legen wir ein eingehendes Schema für ein Ticket an:
class TicketIn(ModelSchema):
class Config:
model = Ticket
model_fields = ("status",)
Und definieren in api.py einen weiteren Endpunkt.
@api.post("/")
def ticket_add(request, data: TicketIn) -> dict:
ticket = Ticket.objects.create(**data.dict())
return {"result": "success", "id": ticket.id}
Um ein neues Ticket anzulegen, brauchen wir wieder curl:
curl http://127.0.0.1:8000/api/tickets/ -d '{"status":"new"}' -X POST
Falls die Eingabedaten falsch sind, bekommen wir einen Fehler serviert
curl http://127.0.0.1:8000/api/tickets/ -d '{"status":"neu"}' -X POST -vv
curl http://127.0.0.1:8000/api/tickets/3 -d '{"status":"neu"}' -X PUT
Um ein Ticket upzudaten, können wir die HTTP-Methoden put oder patch nutzen. Für put machen wir es so
@api.put("/put/{ticket_id}")
def ticket_put(request, ticket_id: int, payload: TicketIn):
obj = get_object_or_404(Ticket, pk=ticket_id)
for attr, value in payload.dict().items():
if value:
setattr(obj, attr, value)
return {"id": obj.pk}
curl -X PUT http://127.0.0.1:8000/api/tickets/put/3 -d ‚{„status“:“new“}‘
@api.delete("/{ticket_id}")
def ticket_delete(request, ticket_id: int):
obj = get_object_or_404(Ticket, pk=ticket_id)
obj.delete()
return {"success": True}
curl -X DELETE http://127.0.0.1:8000/api/tickets/3