2012-11-28 25 views
124

Sono un principiante nel framework Rango di Django e ho bisogno del vostro consiglio. Sto sviluppando un servizio web. Il servizio deve fornire un'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). Invece, fornisce altri servizi con alcuni risultati di calcolo. Su richiesta il mio servizio esegue alcuni calcoli e restituisce solo i risultati (non memorizza i risultati nel proprio database).Framework Rango di Django: serializzatore non modello

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

  1. Creare la classe che esegue i calcoli. Chiamalo 'CalcClass'. CalcClass utilizza i modelli nel suo lavoro.
    • Params necessari per i calcoli vengono passati al costruttore.
    • Implementare l'operazione di calcolo. Restituisce risultati come 'ResultClass'.
  2. Crea ResultClass.
    • Derivato dall'oggetto.
    • Ha solo attributi contenenti i risultati del calc.
    • Una parte dei risultati del calc è rappresentata come una tupla di tuple. Come ho capito, sarebbe meglio per un'ulteriore serializzazione implementare una classe separata per quei risultati e aggiungere l'elenco di tali oggetti a ResultClass.
  3. Creare Serializer per ResultClass.
    • Deriva da serializers.Serializer.
    • I risultati del calc sono di sola lettura, quindi utilizzare principalmente la classe Field per i campi, anziché le classi specializzate, come IntegerField.
    • Non dovrei eseguire il metodo impl save() né su ResultClass, né su Serializer, perché non ho intenzione di memorizzare i risultati (voglio solo restituirli su richiesta).
    • Serializzatore Impl per risultati annidati (ricordate la tupla di tuple menzionate sopra).
  4. CREATE VIEW per restituire i risultati di calcolo.
    • Deriva da APIView.
    • Serve solo ottenere().
    • In get() creare CalcClass con params recuperati dalla richiesta, chiamare il suo calc(), ottenere ResultClass, creare Serializer e passare il ResultClass ad esso, tornare Response (serializer.data).
  5. URL
    • Non c'è radice api nel mio caso. Dovrei solo avere URL per ottenere vari risultati di calc (calc con parametri diff).
    • Aggiungere il formato format_suffix_patterns per la navigazione api.

Mi sono perso qualcosa? L'approccio è corretto in generale?

risposta

131

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

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

Quindi, in pratica, è sufficiente creare la funzione o la classe che accetta argomenti, esegue tutti i calcoli richiesti e restituisce i risultati in una tupla alla vista API REST. Se JSON e/o XML si adattano alle tue esigenze, django-rest-framework si prenderà cura della serializzazione per te.

In questo caso, è possibile 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 potrebbero aiutarti:

prega di notare che non ho ancora testato questo. E 'pensato solo come esempio, ma dovrebbe funzionare :)

Il 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 

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=json con .json. È inoltre possibile specificare la codifica che si desidera ripristinare aggiungendo "Content-type" o "Accept" alle intestazioni.

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

Spero che questo ti aiuti.

+1

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

+2

Grazie mille, mi ha salvato la giornata. Dovrebbe essere parte della documentazione. – neelix

+3

Ho provato a seguire questo suggerimento ma ottengo: "Non posso applicare DjangoModelPermissions su una vista che non ha proprietà' .model' o '.queryset'.". Ho provato l'esatto esempio fornito. Potrebbe essere qualcosa con la versione recente di django-rest-framework? – Orlando

Problemi correlati