Come scrivere un'API in 3 righe di codice con il framework REST Django

Con solo 3 righe di codice, è possibile creare un endpoint API pronto per l'uso con Django REST Framework.

Ci sono una serie di vantaggi nello sviluppo con Django. Un vantaggio chiave di un'API REST è che offre una grande flessibilità. Insieme, il framework Django REST è un toolkit potente, vendibile e versatile per la costruzione di API Web.

Sommario

  1. Introduzione a REST
  2. Che cos'è REST?
  3. Cosa non è REST
  4. Risorse REST
  5. Perché usare il framework Django REST
  6. Introduzione a Django REST Framework
    6.1 Serializzatori
    6.2 Visualizzazioni / Visualizzazioni
    6.3 Router
    6.4 Renderer
    6.5 Autenticazione
    6.6 Autorizzazioni
    6.7 Filtro
    6.8 Ordine
    6.9 Azioni personalizzate (risorse nidificate)
  7. Conclusione

Per chi è questo articolo?

Questo articolo è destinato agli ingegneri del software che già utilizzano Django e hanno già alcune conoscenze nell'API REST.

Se devi creare API REST in Django o hai già alcune viste Django che si comportano come endpoint e devono estendere / migliorare il loro comportamento, questo articolo fa per te.

Che cos'è REST?

REST - Representational State Transfer è un modello architettonico utilizzato per progettare architetture software distribuite basate sulla comunicazione di rete. REST è uno dei principali modelli del protocollo HTTP che è stato descritto da Roy Fielding nella sua tesi di dottorato e adottato come modello da utilizzare nell'evoluzione dell'architettura del protocollo HTTP.

Principi chiave di REST

La maggior parte delle presentazioni di REST iniziano con una definizione e una storia formali. Salterò su questo e ti darò una definizione semplice e pragmatica:

REST è un insieme di principi che definiscono come dovrebbero essere usati gli standard Web come HTTP e URL (che spesso differiscono un po 'da quello che fanno attualmente molte persone).

Il vantaggio è che se aderisci ai principi REST durante la progettazione della tua applicazione, avrai un sistema che utilizza l'architettura Web a tuo vantaggio.

I cinque principi fondamentali di REST sono i seguenti:

  • Dai a tutte le cose un identificatore
  • Collega le cose insieme
  • Utilizzare metodi standardizzati
  • Funzionalità con più rappresentazioni
  • Comunicare senza stato

Cosa non è REST

Molte persone pensano che se un'API restituisce JSON è REST o che REST è un protocollo come HTTP o FTP, ma no.

REST è un MODELLO architettonico basato su risorse HTTP come GET / HEAD / POST / PUT / DELETE.

Inoltre, a JSON non piace solo un'API RESTFul, come vedremo più avanti, il Django REST Framework ha renderer per vari tipi di ritorno, come LaTEx, CSV e (il tanto odiato) XML.

Pertanto, REST non è sinonimo di JSON, sebbene sia il renderer più utilizzato.

Anche REST non è la soluzione a tutti i problemi.

Esistono diverse soluzioni basate su SOAP che per vari motivi non sarebbero in grado di rispondere alle richieste in un'API RESTFul, sia perché richiedono un lavoro ENORME o perché semplicemente non possono conformarsi agli standard stabiliti che compongono il modello REST. Un buon esempio di questi sono enormi applicazioni monolitiche come i vecchi ERP che hanno endpoint SOAP.

Risorse REST

Il modello architettonico REST si basa su 3 concetti: azioni, risorse e rappresentazioni:

risorse

Le funzionalità di REST si riferiscono ai SOSTANTI della tua API o a cosa ti riferisci. Di solito in Django, le tue risorse API sono mappate ai tuoi modelli tramite serializzatori.

Esempio - Utente, Fattura, Gruppo.

utente di classe (model.Model):
 name = models.CharField (max_length = 255)
 cognome = models.CharField (max_length = 255)
classe Invoice (models.Model):
 user = models.ForeignKey (Utente)
 numero = modelli.CharField (max_length = 25)

ogni modello può fare riferimento a una risorsa nella sua API REST

Azioni

Le azioni determinano ciò che il client che sta utilizzando l'API desidera fare con una determinata risorsa. Le azioni sono mappate su VERBI HTTP, il più comunemente usato è GET / POST / PUT / PATCH / DELETE (Non entreremo nei dettagli sui verbi HTTP.)

I principi RESTful forniscono strategie per gestire le azioni CRUD usando metodi HTTP mappati

GET / users # Restituisce un elenco di utenti
GET / users / # Restituisce informazioni per un utente specifico
POST / users # Crea un nuovo utente
PUT / users / # Modifica completamente un utente specifico
PATCH / users / # Aggiorna parzialmente un utente specifico
DELETE / users / # Rimuovi un utente specifico

Uno dei grandi vantaggi di REST è che tutte queste azioni sono già implementate automaticamente senza dover creare nuovi URL o azioni nidificate. In questo modo, l'uso della risorsa è reso chiaro e pulito.

Suggerimento per le buone pratiche: i nomi degli endpoint devono essere al plurale. Anche se può sembrare strano descrivere una singola istanza al plurale, questo per mantenere coerente il formato dell'URL e non dover affrontare strane pluralizzazioni, migliora anche la leggibilità dell'API per gli utenti in futuro.

Rappresentanze

Le rappresentazioni REST sono il modo in cui i dati di una risorsa vengono visualizzati a chiunque faccia una richiesta a un endpoint specifico.

In genere, queste funzioni sono visualizzate in formato JSON (possono avere altri formati). Fondamentalmente, tutti i dati nei modelli, dopo la serializzazione, sono rappresentati come oggetti JSON al ritorno della richiesta

OTTIENI / utenti
[
 {
     "Id": 1,
     “Name“: “Anakin SkyWalker“,
 },
 {
     "Id": 2,
     “Name“: “Luke SkyWalker“,
 },
 {
     "Id": 3,
     “Name“: “Han Solo“,
 }
]

Dopo questa breve introduzione ai concetti di base (molto basilari) delle API REST, scopriamo come (e perché) implementiamo questi schemi in un'app Django nuova o esistente.

Perché usare il framework Django REST

Ok, REST è bello, ma perché dovrei scegliere di usare Django REST Framework? Perché non usare un'altra libreria o anche solo le viste standard di Django?

La risposta rapida a questa domanda è semplice: produttività.

Come indica l'articolo del titolo, sono necessarie solo poche righe per far funzionare un endpoint. Non è necessaria alcuna magia, né è necessario collegare migliaia di fili.

Il livello di astrazione fornito dal DRF è abbastanza alto da preoccuparti solo di 1 dei principi di base: risorse.

Inoltre, ci sono altri vantaggi in un framework REST Django:

  • API HTML navigabile
  • Team di sviluppo / supporto a tempo pieno
  • Serializzazione dei dati ORM e NON-ORM
  • Comunità
  • Una delle migliori documentazioni tra le librerie Python
  • Autenticazione collegabile con theAuth, theAuth2 e Social Auth
  • Libs di terze parti

L'ecosistema attorno al DRF è immenso, con una vasta gamma di librerie che estendono il comportamento predefinito del DRF (che è già di terze parti).

Introduzione a Django REST Framework

Vedremo ora alcune delle cose che DRF offre immediatamente, senza dover installare altri pacchetti. Puoi approfondire ciascuno di questi temi nella stessa documentazione DRF.

Come ho detto prima, ha una delle migliori librerie e include anche un tutorial su come costruire la tua API usando DRF, oltre ad essere ricco di esempi e possibili soluzioni tra i problemi.

serializzatori

I serializzatori consentono di convertire dati complessi come queryset e istanze del modello in tipi Python nativi in ​​modo da renderli facilmente come JSON, XML o altri tipi di contenuto.

I serializzatori forniscono anche la deserializzazione, consentendo di riconvertire i dati analizzati in dati complessi dopo la convalida. Sono responsabili della trasformazione dei tuoi modelli in RISORSE nella tua API quando sono connessi a un ViewSet, il che ci porta al punto successivo.

da rest_framework importare serializzatori
da main.models import Cat, Dog
class DogSerializer (serializers.ModelSerializer):
    classe Meta:
        modello = Cane
        campi = ("proprietario", "nome", "compleanno")
        read_only_fields = ("proprietario",)
class CatSerializer (serializers.ModelSerializer):
 classe Meta:
    modello = Cat
    campi = ("proprietario", "nome", "compleanno")
    read_only_fields = ("proprietario",)

* Un serializzatore assomiglia molto a un modello Django.

ViewSets

I ViewSet, come già dice il nome, sono insiemi di Views che astraggono comportamenti relativi alle azioni eseguite dall'utente come verbi HTTP GET / POST / PUT / DELETE.

A prima vista, i ViewSet sono viste basate su classi che forniscono azioni come .list () o .create ().

Con solo 3 righe di codice, è possibile creare un endpoint pronto all'uso che risponde a TUTTE LE AZIONI DI RIPOSO.

A un livello inferiore, ciascuna vista all'interno di un ViewSet rappresenta un'azione nel loro endpoint, come .get (), .post (), .delete () e così via. Puoi vedere come DRF implementa ogni vista su questo sito - http://www.cdrf.co/

da rest_framework importare viewets, autorizzazioni
da main.models import Cat, Dog
da .permissions import IsOwnerOrReadOnly
da .serializers import CatSerializer, DogSerializer
# Crea le tue opinioni qui.
classe BaseViewSet (viewset. ModelViewSet):
    permesso_classes = [Permissions.IsAuthenticated, IsOwnerOrReadOnly]
def get_queryset (self):
    qs = self.queryset.filter (owner = self.request.user)
    restituire qs
def perform_create (self, serializzatore):
    serializer.save (proprietario = self.request.user)
classe DogViewSet (BaseViewSet):
    serializer_class = DogSerializer
    queryset = Dog.objects.all ()
classe CatViewSet (BaseViewSet):
    serializer_class = CatSerializer
    queryset = Cat.objects.all ()

Visualizzazioni

Le viste sono semplici classi che ti offrono maggiore libertà nell'implementazione, puoi creare azioni personalizzate che di solito non hanno una connessione diretta con i Modelli o non fanno CRUD.

dallo stato di importazione di rest_framework
da rest_framework.views importa APIView
da rest_framework.response import Risposta
da .permissions import IsOwnerOrReadOnly
da .models import Dog
classe DogFeedView (APIView):
 authentication_classes = (authentication.TokenAuthentication,)
 permesso_classe = (IsOwnerOrReadOnly,)
 
 def get (self, request, pk = None):
     dog = get_object_or_404 (Cane, pk = pk)
     dog.feed ()
     risposta di ritorno ({“msg“: “Dog fed“, status = status.HTTP_200_OK})

Router

I router in DRF funzionano registrando i viewet registrati, la classe che fornisce 2 parametri obbligatori ("prefisso", Classe), il DRF registra automaticamente 2 route nelle seguenti impostazioni predefinite. Per creare percorsi per viste semplici, puoi aggiungere un percorso manualmente, proprio come in Django.

Pattern URL: ^ dogs / $ Name: "dog-list"
Pattern URL: ^ dogs / {pk} / $ Name: "dettaglio cane"

dai router di importazione rest_framework
da .views import DogViewSet, CatViewSet, DogFeedView
router = routers.DefaultRouter (trailing_slash = False)
router.register ("dogs", DogViewSet)
router.register ("gatti", CatViewSet)
urlpatterns = router.urls
urlpatterns + = [
    url (r'dogs / (? P  [\ d] +) / feed / $ ’, DogFeedView.as_view (), name = dogfeed)
]

Autenticazione

Esistono quattro metodi di autenticazione principali per impostazione predefinita

  1. SessionAuthentication
    Questo schema di autenticazione utilizza il backend di sessione predefinito di Django per l'autenticazione. L'autenticazione della sessione è appropriata per i client AJAX in esecuzione nello stesso contesto di sessione del sito Web.
  2. BasicAuthentication
     Questo schema di autenticazione utilizza l'autenticazione di base HTTP, firmata con il nome utente e la password di un utente. L'autenticazione di base è generalmente appropriata solo per i test.
  3. TokenAuthentication
     Questo schema di autenticazione utilizza un semplice schema di autenticazione HTTP basato su token. L'autenticazione con token è appropriata per le configurazioni client-server, come desktop desktop e client mobili.
  4. RemoteUserAuthentication
     Questo schema di autenticazione consente di delegare l'autenticazione al server Web, che imposta la variabile di ambiente REMOTE_USER. I server remoti più comuni sono NGINX e Apache

Inoltre, è possibile installare librerie per collegare OAuth, OAuth2 e persino SocialAuth per accedere con i provider sociali.

Le classi di autenticazione possono essere definite nel contesto dell'applicazione o a livello di viste / viste. Puoi anche definire più classi di autenticazione, rendendo la tua API estremamente flessibile.

da rest_framework.authentication import TokenAuthentication, BasicAuthentication
(... altro codice di definizione)
classe DogFeedView (APIView):
 authentication_classes = (TokenAuthentication, BasicAuthentication)
 (altro codice di definizione ...)
...

E nel contesto dell'applicazione

REST_FRAMEWORK = {
 "DEFAULT_AUTHENTICATION_CLASSES": (
 ‘Rest_framework.authentication.BasicAuthentication’,
 "Rest_framework.authentication.SessionAuthentication",
 )
}

renderers

Esistono diversi renderer disponibili nel DRF, che visualizzano i tuoi dati nel modo più conveniente per il tuo cliente.

  • Incorporato
    - JSON
    - TemplateHTML
    - StaticHTML
    - API consultabile
    - Amministratore
    - HTMLForm
    - MultiPart
  • Biblioteche di terze parti
    - YAML
    - XML
    - JSONP
    - MessagePack
    - CSV
    - UltraJSON
    - CamelCase JSON
    - Panda (CSV, Excel, JPG)
    - LaTex

Come la maggior parte dei moduli DRF, i renderer possono anche essere configurati nel contesto generale o a livello di vista, semplicemente inserendo l'URL nel parametro

? format = o http: // localhost: 8000 / api / resource.

...
(... altro codice di definizione)
 dai renderer di importazione rest_framework
 da rest_framework_xml.renderers importa XMLRenderer
classe DogFeedView (APIView):
 renderer_classes = (renderers.TemplateHTMLRenderer, renderers.JSONRenderer, XMLRenderer)
 (altro codice di definizione ...)
...

O nel contesto dell'applicazione

REST_FRAMEWORK = {
 "DEFAULT_RENDERER_CLASSES": (
 "Rest_framework.renderers.JSONRenderer",
 "Rest_framework.renderers.BrowsableAPIRenderer",
 )
}

permessi

Insieme all'autenticazione, le autorizzazioni definiscono quando e come un client può accedere a una particolare funzione API. Possono anche essere definiti da view / viewset o nel contesto generale dell'applicazione. Puoi anche creare autorizzazioni personalizzate.

...
(... altro codice di definizione)
 dai renderer di importazione rest_framework
 da rest_framework_xml.renderers importa XMLRenderer

classe DogFeedView (APIView):
    renderer_classes = (renderers.TemplateHTMLRenderer, renderers.JSONRenderer, XMLRenderer)
    (altro codice di definizione ...)
...

E nel contesto dell'applicazione

REST_FRAMEWORK = {
 "DEFAULT_PERMISSION_CLASSES": (
 "Rest_framework.permissions.IsAuthenticated",
 )
}

Permesso personalizzato:

da rest_framework.permissions importa BasePermission
classe IsOwner (BasePermission):
def has_object_permission (self, request, view, obj):
"" "Restituisce` Vero` se viene concesso il permesso, `Falso` altrimenti.“ ““
    return obj.user == request.user

filtraggio

Esistono diversi modi per filtrare il contenuto da offrire in base alle esigenze del cliente. Per abilitare filtri più potenti, è necessario installare un'estensione chiamata django-filter.

Per impostazione predefinita, puoi filtrare in 3 modi:

  • Via Query Params
    http: // localhost: 8000 / api / v1 / cani Name = rex
  • Per URL Param
    url (″ ^ acquisti / (? P. +) / $ ’, PurchaseList.as_view ())
  • Sostituzione del metodo di restituzione predefinito dell'attributo queryset
da myapp.models importare l'acquisto
da myapp.serializers importare PurchaseSerializer
da rest_framework import generics
class PurchaseList (generics.ListAPIView):
    serializer_class = PurchaseSerializer
def get_queryset (self):
 “” “
 Questa vista non dovrebbe restituire un elenco di tutti gli acquisti. Attualmente per l'utente autenticato
“‘’
 user = self.request.user
 return Purchase.objects.filter (acquirente = utente)

Filtro - Filtro di ricerca

Uno dei filtri di meccanica dei filtri più potenti è il filtro di ricerca, che consente all'utente di effettuare ricerche nel proprio database come se stessero utilizzando i queryset ORM di Django, è sufficiente inserire il parametro "cerca" nell'URL (che può essere modificato nelle impostazioni)

http://example.com/api/users?search=russell

È anche possibile eseguire il filtraggio su ManyToManyand ForeignKeyrelationships nello stesso modo in cui eseguiamo query inverse utilizzando il doppio trattino basso (__) nei queryset di Django.

class UserListView (generics.ListAPIView):
    queryset = User.objects.all ()
    serializer_class = UserSerializer
    filter_backends = (filters.SearchFilter,)
    search_fields = ("nome utente", "email", "profilo__profession")

ordinazione

Per impostazione predefinita, l'ordinamento DRF segue ciò che è determinato dai modelli. Per definire altri campi, è sufficiente definire due attributi nella vista / insieme di viste che si desidera:

class UserListView (generics.ListAPIView):
 queryset = User.objects.all ()
 serializer_class = UserSerializer
 filter_backends = (filters.OrderingFilter,)
 ordering_fields = ("nome utente", "email")

Quindi basta dire all'URL in quale ordine si desidera che la rappresentazione venga restituita http://example.com/api/users?ordering=username

Azioni personalizzate (router nidificati)

Non sempre i "verbi" HTML standard risolvono il nostro problema. Quando stiamo studiando la nostra API, identifichiamo i verbi che non esistono per impostazione predefinita, ma possiamo "estendere" il protocollo creando azioni personalizzate per rappresentare questi verbi. Ad esempio, abbiamo bisogno di un verbo END (Azione) per terminare una CHIAMATA (Risorsa), ma non abbiamo questo verbo per impostazione predefinita nella definizione HTTP, quindi possiamo "estendere" il PUT / POST con una risorsa nidificata. Ricorda che i ViewSet implementano azioni HTTP come metodi? Così…

classe CallViewSet (viewsets.ModelViewSet):
 ... (altra definizione di codice)
 
    @detail_route (metodi = ["put" ", URL_path =" end-call ")
    def end_call (self, request, identifier = None):
    “” “Termina la chiamata specificata.“ “”
        call = self.get_object ()
        timestamp = request.data.get ("timestamp", nessuno)
        provare:
            in caso contrario call.has_ended:
            call.end_call (timestamp = timestamp)
        tranne ValueError come exc:
            raise serializers.ValidationError (str (exc))
        serializer = self.serializer_class (istanza = chiamata)
        risposta di ritorno (serializer.data, status = status.HTTP_200_OK)

Risorsa nidificata per la chiamata della route http: // localhost: 8000 / api / v1 / Calls / / end-call /

Conclusione

Abbiamo visto come Django REST Framework semplifichi la creazione di risorse di un'API REST, aumentando notevolmente la nostra produttività.

DRF non si limita solo agli argomenti trattati in questo articolo, nella documentazione DRF sono presenti molte altre funzionalità correlate alle API REST come limitazione, documentazione, validatori, controllo delle versioni e molto altro.

DRF ha anche funzionalità per supportare il modello API HATEOAS. Come Django, DRF è estremamente potente, affidabile e può aiutarti a risolvere i tuoi problemi con il minimo sforzo.

Se hai domande, inseriscile nei commenti e ti ricontatterò. La mia prima lingua è il portoghese, quindi li affronterò come posso. Grazie, Google traduttore. ;-)

Se hai creato qualcosa di interessante con l'API REST di Django, inseriscilo anche nei commenti. Mi piacerebbe dargli un'occhiata.

ULTERIORI RISORSE QUADRO DI RESTO DJANGO

  • https://www.infoq.com/articles/rest-introduction
  • https://www.oreilly.com/learning/how-to-design-a-restful-api-architecture-from-a-human-language-spec
  • http://www.django-rest-framework.org

In Crowdbotics, aiuto le aziende a costruire cose interessanti con Django (tra le altre cose). Se hai un progetto Django in cui hai bisogno di risorse aggiuntive per gli sviluppatori, scrivici. Crowbotics è in grado di stimare i tempi di costruzione per determinate specifiche di prodotto e funzionalità e fornire sviluppatori Django specializzati quando ne hai bisogno. Se stai costruendo con Django, dai un'occhiata a Crowdbotics.

Grazie a William Wickey per l'aiuto nella modifica e traduzione di questo post.

Costruire un'app Web o mobile?

Crowdbotics è il modo più veloce per creare, avviare e ridimensionare un'applicazione.

Sviluppatore? Prova Crowdbotics App Builder per creare rapidamente impalcature e distribuire app con una varietà di framework popolari.

Occupato o non tecnico? Unisciti a centinaia di team felici che creano software con PM di Crowdbotics e sviluppatori esperti. Scorri la cronologia e i costi con Crowdbotics Managed App Development gratuitamente.