2012-11-28 13 views
124

Ich bin Anfänger in Django REST-Framework und brauche Ihren Rat. Ich entwickle einen Webservice. Der Dienst muss eine REST-Schnittstelle zu anderen Diensten bereitstellen. Die REST-Schnittstelle, die ich implementieren muss, arbeitet nicht direkt mit meinen Modellen (ich meine die Operationen get, put, post, delete). Stattdessen bietet es andere Dienste mit einigen Berechnungsergebnissen. Bei einer Anfrage führt mein Dienst einige Berechnungen durch und gibt die Ergebnisse nur zurück (speichert die Ergebnisse nicht in einer eigenen Datenbank).Django REST-Framework: Nicht-Modell-Serializer

Unten ist mein Verständnis davon, wie diese REST-Schnittstelle implementiert werden könnte. Korrigiere mich, wenn ich falsch liege.

  1. Klasse erstellen, die die Berechnungen durchführt. Nenne es 'CalcClass'. CalcClass verwendet die Modelle in seiner Arbeit.
    • Parameter, die für die Berechnungen erforderlich sind, werden an den Konstruktor übergeben.
    • Implementieren Sie den Berechnungsvorgang. Es gibt Ergebnisse als 'ResultClass' zurück.
  2. Erstellen Sie ResultClass.
    • Vom Objekt abgeleitet.
    • Es hat nur nur Attribute, die die calc-Ergebnisse enthalten.
    • Ein Teil der Berechnungsergebnisse wird als Tupel-Tupel dargestellt. Wie ich es verstehe, wäre es für die weitere Serialisierung besser, eine separate Klasse für diese Ergebnisse zu implementieren und eine Liste solcher Objekte zu ResultClass hinzuzufügen.
  3. Erstellen Sie Serializer für ResultClass.
    • Ableitung von Serializers.Serializer.
    • Die Kalkulationsergebnisse sind schreibgeschützt. Verwenden Sie daher hauptsächlich die Feldklasse für Felder anstelle von spezialisierten Klassen wie IntegerField.
    • Ich sollte nicht save() -Methode weder auf ResultClass, noch auf Serializer impl, weil ich nicht die Ergebnisse speichern werde (ich möchte nur auf Anfrage zurückgeben).
    • Impl Serializer für verschachtelte Ergebnisse (erinnere Tupel der oben genannten Tupel).
  4. Ansicht erstellen, um Berechnungsergebnisse zurückzugeben.
    • Ableitung von APIView.
    • Brauchen Sie nur().
    • In Get() CalcClass mit Params aus der Anfrage abgerufen, rufen Sie seine calc(), Get ResultClass, erstellen Serializer und übergeben Sie die ResultClass, Rückgabe Response (serializer.data).
  5. URLs
    • Es gibt keine api Wurzel in meinem Fall. Ich sollte nur URLs haben, um verschiedene calc-Ergebnisse zu erhalten (calc mit diff params).
    • Fügen Sie den Aufruf format_suffix_patterns für api-Browsing hinzu.

Habe ich etwas verpasst? Ist der Ansatz im Allgemeinen korrekt?

Antwort

131

Django-Rest-Framework funktioniert auch ohne Bindung an ein Modell. Ihr Ansatz klingt gut, aber ich glaube, Sie können einige der Schritte kürzen, um alles zum Laufen zu bringen.

Zum Beispiel kommt Rest Framework mit ein paar eingebauten Renderer. Out-of-the-Box kann JSON und XML an den API-Consumer zurückgeben. Sie können YAML auch aktivieren, indem Sie einfach das erforderliche Python-Modul installieren. Django-rest-framework gibt jedes Basisobjekt wie dict, list und tuple ohne zusätzliche Arbeit aus.

Also im Grunde müssen Sie nur die Funktion oder Klasse erstellen, die Argumente übernimmt, alle erforderlichen Berechnungen durchführt und ihre Ergebnisse in einem Tupel an die REST-API-Sicht zurückgibt. Wenn JSON und/oder XML Ihren Anforderungen entsprechen, kümmert sich django-rest-framework um die Serialisierung für Sie.

Sie können die Schritte 2 und 3 in diesem Fall überspringen und nur eine Klasse für Berechnungen und eine für die Präsentation für den API-Verbraucher verwenden.

Hier sind ein paar Schnipsel Ihnen helfen kann:

Bitte beachten Sie, dass ich nicht getestet haben. Es ist nur als Beispiel gemeint, aber es sollte funktionieren :)

Die 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 

Der REST-Ansicht:

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 

Ihre 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'), 
) 

Dieser Code sollte beim Zugriff auf http://example.com/api/v1.0/resource/?format=json eine Liste von Listen ausgeben. Wenn Sie ein Suffix verwenden, können Sie ?format=json durch .json ersetzen. Sie können auch die Kodierung angeben, die Sie wiederherstellen möchten, indem Sie "Content-type" oder "Accept" zu den Headern hinzufügen.

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

Hoffe, das hilft Ihnen aus.

+1

Hallo Gabriel! Vielen Dank für Ihre Antwort! Ich habe bereits umgesetzt, was ich nach meinem Plan brauche. Funktioniert gut! Ich benutzte den Serializer für bessere json Ausgabe. – Zakhar

+2

Vielen Dank, es hat meinen Tag gerettet. Es sollte Teil der Dokumentation sein. – neelix

+3

Ich habe versucht, diesem Vorschlag zu folgen, aber ich bekomme: "DjangoModelPermissions kann nicht auf eine Ansicht angewendet werden, die keine' .model' oder '.queryset' Eigenschaft hat.". Ich habe das genaue Beispiel ausprobiert. Könnte es etwas mit der aktuellen Version von django-rest-framework sein? – Orlando

Verwandte Themen