Django REST Framework: Serializer ohne Modell


158

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

Im Folgenden verstehe ich, wie diese REST-Schnittstelle implementiert werden kann. Korrigieren Sie mich, wenn ich falsch liege.

  1. Erstellen Sie eine Klasse, die die Berechnungen durchführt. Nennen Sie es 'CalcClass'. CalcClass verwendet die Modelle in seiner Arbeit.
    • Die für die Berechnungen erforderlichen Parameter werden an den Konstruktor übergeben.
    • Implementieren Sie die Berechnungsoperation. Es gibt Ergebnisse als 'ResultClass' zurück.
  2. ResultClass erstellen.
    • Abgeleitet vom Objekt.
    • Es enthält nur Attribute, die die Berechnungsergebnisse enthalten.
    • Ein Teil der Berechnungsergebnisse wird als Tupel von Tupeln dargestellt. Soweit ich weiß, ist es für die weitere Serialisierung besser, eine separate Klasse für diese Ergebnisse zu implementieren und ResultClass eine Liste solcher Objekte hinzuzufügen.
  3. Erstellen Sie den Serializer für ResultClass.
    • Ableiten von Serializers.Serializer.
    • Die Berechnungsergebnisse sind schreibgeschützt. Verwenden Sie daher hauptsächlich Feldklassen für Felder anstelle von Spezialklassen wie IntegerField.
    • Ich sollte die save () -Methode weder in ResultClass noch in Serializer implementieren, da ich die Ergebnisse nicht speichern werde (ich möchte sie nur auf Anfrage zurückgeben).
    • Impl Serializer für verschachtelte Ergebnisse (denken Sie an das oben erwähnte Tupel Tupel).
  4. Ansicht erstellen, um Berechnungsergebnisse zurückzugeben.
    • Ableiten von APIView.
    • Muss nur bekommen ().
    • Erstellen Sie in get () CalcClass mit Parametern, die aus der Anforderung abgerufen wurden, rufen Sie calc () auf, rufen Sie ResultClass ab, erstellen Sie Serializer und übergeben Sie die ResultClass an sie, und geben Sie Response (serializer.data) zurück.
  5. URLs
    • In meinem Fall gibt es keine API-Wurzel. Ich sollte nur URLs haben, um verschiedene Berechnungsergebnisse zu erhalten (Berechnung mit diff-Parametern).
    • Fügen Sie aufrufende format_suffix_patterns für das API-Browsing hinzu.

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


Dieser Ansatz ist korrekt und sieht für mich tatsächlich eleganter aus als die akzeptierte Antwort (Ergebnisdaten, die in einem wiederverwendbaren Ergebnistyp gekapselt sind). Aber am Ende des Tages ist dies meistens eine Frage der persönlichen Präferenz und beide Ansätze machen den Job.
zepp.lee

Antworten:


157

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

Zum Beispiel enthält das Rest-Framework einige integrierte Renderer. Standardmäßig können JSON und XML an den API-Consumer zurückgegeben werden. Sie können YAML auch aktivieren, indem Sie einfach das erforderliche Python-Modul installieren. Das Django-Rest-Framework gibt alle grundlegenden Objekte wie Diktat, Liste und Tupel aus, ohne dass Sie zusätzliche Arbeit leisten müssen.

Grundsätzlich müssen Sie also nur die Funktion oder Klasse erstellen, die Argumente aufnimmt, alle erforderlichen Berechnungen durchführt und die Ergebnisse in einem Tupel an die REST-API-Ansicht zurückgibt. Wenn JSON und / oder XML Ihren Anforderungen entsprechen, übernimmt django-rest-framework die Serialisierung für Sie.

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

Hier sind einige Ausschnitte, die Ihnen helfen können:

Bitte beachten Sie, dass ich dies nicht getestet habe. Es ist nur als Beispiel gedacht, 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

Die 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 eine Liste von Listen ausgeben, wenn Sie auf http://example.com/api/v1.0/resource/?format=json zugreifen . Bei Verwendung eines Suffix, können Sie ersetzen ?format=jsonmit .json. Sie können auch die Codierung angeben, die Sie durch Hinzufügen "Content-type"oder "Accept"zu den Headern zurückerhalten möchten .

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

Hoffe das hilft dir weiter.


2
Hallo Gabriel! Vielen Dank für Ihre Antwort! Ich habe bereits implementiert, was ich nach meinem Plan brauche. Funktioniert gut! Ich habe den Serializer für eine bessere JSON-Ausgabe verwendet.
Zakhar

3
Ich habe versucht, diesem Vorschlag zu folgen, erhalte jedoch Folgendes: "DjangoModelPermissions kann nicht auf eine Ansicht angewendet werden, die keine .modeloder keine .querysetEigenschaft hat." Ich habe das genaue Beispiel ausprobiert. Könnte es etwas mit der aktuellen Version von Django-Rest-Framework sein?
Orlando

Dieses Beispiel wurde vor einiger Zeit geschrieben. Ich hatte seitdem keine Gelegenheit mehr, wieder mit Django zu arbeiten. Aber vielleicht finden Sie hier etwas Nützliches: django-rest-framework.org/api-guide/routers
Gabriel Samfira

1
Dieses Beispiel ist genau das, was ich für meinen Bedarf brauchte, ist ein Dienst, der einige Operationen ohne einen Serializer ohne Modell ausführt!
Khalil TABBAL

@Orlando: Sehen Sie hier, wie Sie eine Berechtigungslogik implementieren, die für eine Nichtmodellansicht mit djang-restframework 3 spezifisch ist
djangonaut

-1

In der urls.py erfordert die Funktion login_required

from django.contrib.auth.decorators import login_required

Wenn dies nur ein Kommentar anstelle einer Antwort ist, sollten Sie die add a commentSitzung verwenden
lucascavalcante
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.