Taula de continguts

APIs amb Django Ninja

Django Ninja és una llibreria per a fer APIs alternativa a la clàssica Django REST Framework (que podeu veure a l'article Django API) i fortament inspirada en la molt adoptada recentment FastAPI.

El principal avantatge és certa simplicitat per crear els endpoints.

Referències:

, , , , , , , , ,


Quickstart

És relativament fàcil acostar-se a Django Ninja amb la seva documentació:


Autenticació

Destaquem dos mètodes d'autenticació molt estandarditzats:

Es poden implementar les dues amb aquest codi:

api.py
from django.contrib.auth import authenticate
from ninja import NinjaAPI, Schema
from ninja.security import HttpBasicAuth, HttpBearer
from typing import List, Optional
from .models import *
import secrets
 
api = NinjaAPI()
 
# Autenticació bàsica
class BasicAuth(HttpBasicAuth):
    def authenticate(self, request, username, password):
        user = authenticate(username=username, password=password)
        if user:
            # Genera un token simple
            token = secrets.token_hex(16)
            user.auth_token = token
            user.save()
            return token
        return None
 
# Autenticació per Token Bearer
class AuthBearer(HttpBearer):
    def authenticate(self, request, token):
        try:
            user = Usuari.objects.get(auth_token=token)
            return user
        except Usuari.DoesNotExist:
            return None
 
# Endpoint per obtenir un token, accés amb BasicAuth
# amb o sense "trailing slash"
@api.get("/token", auth=BasicAuth())
@api.get("/token/", auth=BasicAuth())
def obtenir_token(request):
    return {"token": request.auth}
 
# Exemple d'endpoint per llistar els llibres, accés amb TokenAuth
class LlibreOut(Schema):
    id: int
    titol: str
    editorial: Optional[str]
 
@api.get("/llibres/", response=List[LlibreOut], auth=AuthBearer())
def get_llibres(request):
    qs = Llibre.objects.all()
    return qs

A part, també caldrà afegir la columna auth_token al model Usuari que cal personalitzar:

models.py
from django.contrib.auth.models import AbstractUser
 
class Usuari(AbstractUser):
    auth_token = models.CharField(max_length=32,blank=True,null=True)
    # + altres atributs que es vulguin afegir...

I a settings.py:

settings.py
AUTH_USER_MODEL = 'myapp.Usuari'


Mes curl

El típic exemple de request amb Basic Authentication seria:

curl -u admin:admin123 http://localhost:8000/api/users/

De vegades ens pot interessar una alternativa enviant les dades codificades en base64 en els headers:

curl -H 'Authorization:Basic YWRtaW46YWRtaW4xMjM=' http://localhost:8000/api/users/

Per obtenir el hash en base64 es pot fer:

echo -n "admin:admin123" | base64

Per aconseguir un pretty print del JSON es pot fer amb la utilitat jq

curl -u admin:admin123 http://localhost:8000/api/users/ | jq

Per instal·lar jq es pot fer:

sudo apt install jq