Django REST framework: serializzatore non modello


158

Sono principiante nel framework REST di Django e ho bisogno del tuo consiglio. Sto sviluppando un servizio web. Il servizio deve fornire l'interfaccia REST ad altri servizi. L'interfaccia REST, che devo implementare, non funziona direttamente con i miei modelli (intendo le operazioni get, put, post, delete). Fornisce invece altri servizi con alcuni risultati di calcolo. Su richiesta, il mio servizio effettua alcuni calcoli e restituisce i risultati (non memorizza i risultati nel proprio database).

Di seguito è la mia comprensione di come tale interfaccia REST potrebbe essere implementata. Correggimi, se sbaglio.

  1. Crea una classe che effettua i calcoli. Chiamalo "CalcClass". CalcClass utilizza i modelli nel suo lavoro.
    • I parametri necessari per i calcoli vengono passati al costruttore.
    • Implementare l'operazione calc. Restituisce i risultati come 'ResultClass'.
  2. Crea ResultClass.
    • Derivato dall'oggetto.
    • Ha solo attributi che contengono i risultati di calc.
    • Una parte dei risultati di calc è rappresentata come tupla di tuple. A quanto ho capito, sarebbe meglio per un'ulteriore serializzazione implementare una classe separata per tali risultati e aggiungere un elenco di tali oggetti a ResultClass.
  3. Crea serializzatore per ResultClass.
    • Deriva da serializzatori.Serializer.
    • I risultati di calc sono di sola lettura, quindi utilizza principalmente la classe Field per i campi, anziché le classi specializzate, come IntegerField.
    • Non dovrei impl il metodo save () né su ResultClass, né su Serializer, perché non ho intenzione di memorizzare i risultati (voglio solo restituirli su richiesta).
    • Serializzatore Impl per risultati nidificati (ricordare la tupla di tuple sopra menzionata).
  4. Crea vista per restituire i risultati del calcolo.
    • Deriva da APIView.
    • Ho solo bisogno di ottenere ().
    • In get () crea CalcClass con i parametri recuperati dalla richiesta, chiama calc (), ottieni ResultClass, crea Serializer e passa la ResultClass ad esso, restituisce Response (serializer.data).
  5. URL
    • Nel mio caso non esiste una radice API. Dovrei avere solo URL per ottenere vari risultati di calc (calc con parametri diff).
    • Aggiungi chiamando format_suffix_patterns per la navigazione API.

Ho dimenticato qualcosa? L'approccio è corretto in generale?


Questo approccio è corretto e per me sembra in realtà più elegante della risposta accettata (dati dei risultati incapsulati in un tipo di risultato riutilizzabile). Ma alla fine questa è principalmente una questione di preferenze personali ed entrambi gli approcci fanno il lavoro.
zepp.lee,

Risposte:


157

Django-rest-framework funziona bene anche senza legarlo a un modello. Il tuo approccio suona bene, ma credo che tu possa tagliare alcuni dei passaggi per far funzionare tutto.

Ad esempio, il framework di riposo viene fornito con alcuni renderer integrati. Immediatamente può restituire JSON e XML al consumatore API. Puoi anche abilitare YAML semplicemente installando il modulo python richiesto. Django-rest-framework produrrà qualsiasi oggetto base come dict, list e tuple senza alcun lavoro aggiuntivo da parte tua.

Quindi in pratica devi solo creare la funzione o la classe che accetta gli argomenti, esegue tutti i calcoli richiesti e restituisce i suoi risultati in una tupla alla vista API REST. Se JSON e / o XML soddisfano le tue esigenze, django-rest-framework si occuperà della serializzazione per te.

In questo caso puoi saltare i passaggi 2 e 3 e utilizzare solo una classe per i calcoli e una per la presentazione al consumatore dell'API.

Ecco alcuni frammenti che possono aiutarti:

Si prega di notare che non ho provato questo. Serve solo come esempio, ma dovrebbe funzionare :)

La CalcClass:

class CalcClass(object):

    def __init__(self, *args, **kw):
        # Initialize any variables you need from the input you get
        pass

    def do_work(self):
        # Do some calculations here
        # returns a tuple ((1,2,3, ), (4,5,6,))
        result = ((1,2,3, ), (4,5,6,)) # final result
        return result

La vista REST:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from MyProject.MyApp import CalcClass


class MyRESTView(APIView):

    def get(self, request, *args, **kw):
        # Process any get params that you may need
        # If you don't need to process get params,
        # you can skip this part
        get_arg1 = request.GET.get('arg1', None)
        get_arg2 = request.GET.get('arg2', None)

        # Any URL parameters get passed in **kw
        myClass = CalcClass(get_arg1, get_arg2, *args, **kw)
        result = myClass.do_work()
        response = Response(result, status=status.HTTP_200_OK)
        return response

Il tuo urls.py:

from MyProject.MyApp.views import MyRESTView
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    # this URL passes resource_id in **kw to MyRESTView
    url(r'^api/v1.0/resource/(?P<resource_id>\d+)[/]?$', login_required(MyRESTView.as_view()), name='my_rest_view'),
    url(r'^api/v1.0/resource[/]?$', login_required(MyRESTView.as_view()), name='my_rest_view'),
)

Questo codice dovrebbe generare un elenco di elenchi quando si accede a http://example.com/api/v1.0/resource/?format=json . Se si utilizza un suffisso, è possibile sostituire ?format=jsoncon .json. Puoi anche specificare la codifica che desideri recuperare aggiungendo "Content-type"o "Accept"alle intestazioni.

[
  [
    1, 
    2, 
    3
  ], 
  [
    4, 
    5, 
    6
  ]
]

Spero che questo ti aiuti.


2
Ciao Gabriel! La ringrazio per la risposta! Ho già implementato ciò di cui ho bisogno secondo il mio piano. Funziona bene! Ho usato il serializzatore per una migliore uscita json.
Zakhar,

3
Ho provato a seguire questo suggerimento ma ottengo: "Impossibile applicare DjangoModelPermissions su una vista che non ha .modelo .querysetproprietà". Ho provato l'esatto esempio fornito. Potrebbe essere qualcosa con la recente versione di django-rest-framework?
Orlando,

Questo esempio è stato scritto qualche tempo fa. Da allora non ho più avuto la possibilità di lavorare con Django. ma potresti trovare qualcosa di utile qui: django-rest-framework.org/api-guide/routers
Gabriel Samfira,

1
Questo esempio è esattamente ciò di cui avevo bisogno per il mio bisogno è un servizio che sta facendo alcune operazioni senza un serializzatore non modello!
Khalil TABBAL

@Orlando: Date un'occhiata qui come implementare il permesso logica specifica per una vista non-modello con Djang-restframework 3: stackoverflow.com/a/34040070/640916
djangonaut

-1

In urls.py, la funzione login_required richiede

from django.contrib.auth.decorators import login_required

se questo è solo un commento invece di una risposta, considera di usare la add a commentsessione
lucascavalcante il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.