Framework Django REST: serializator niemodelowy


158

Jestem początkującym we frameworku Django REST i potrzebuję twojej rady. Rozwijam usługę internetową. Usługa musi zapewniać interfejs REST do innych usług. Interfejs REST, który muszę zaimplementować, nie działa bezpośrednio z moimi modelami (mam na myśli operacje get, put, post, delete). Zamiast tego świadczy inne usługi z niektórymi wynikami obliczeń. Na żądanie mój serwis dokonuje obliczeń i po prostu zwraca wyniki (nie przechowuje wyników we własnej bazie danych).

Poniżej znajduje się moje zrozumienie, w jaki sposób można zaimplementować ten interfejs REST. Popraw mnie, jeśli się mylę.

  1. Utwórz klasę, która wykonuje obliczenia. Nazwij go „CalcClass”. CalcClass wykorzystuje modele w swojej pracy.
    • Parametry potrzebne do obliczeń przekazywane są do konstruktora.
    • Zaimplementuj operację calc. Zwraca wyniki jako „ResultClass”.
  2. Utwórz ResultClass.
    • Pochodzi z obiektu.
    • Ma tylko atrybuty zawierające wyniki obliczeń.
    • Jedna część wyników obliczeń jest reprezentowana jako krotka krotek. Jak rozumiem, dla dalszej serializacji lepiej byłoby zaimplementować oddzielną klasę dla tych wyników i dodać listę takich obiektów do ResultClass.
  3. Utwórz serializator dla ResultClass.
    • Pochodzi z serializatorów.
    • Wyniki obliczeń są tylko do odczytu, więc używaj głównie klasy Field dla pól, zamiast klas specjalistycznych, takich jak IntegerField.
    • Nie powinienem implementować metody save () ani na ResultClass, ani na Serializerze, ponieważ nie zamierzam przechowywać wyników (chcę je tylko zwrócić na żądanie).
    • Impl serializer dla zagnieżdżonych wyników (pamiętaj o krotce krotek wspomnianych powyżej).
  4. Utwórz widok, aby zwrócić wyniki obliczeń.
    • Pochodzą z APIView.
    • Wystarczy pobrać ().
    • W get () utwórz CalcClass z parametrami pobranymi z żądania, wywołaj jego calc (), pobierz ResultClass, utwórz Serializer i przekaż do niego ResultClass, zwróć Response (serializer.data).
  5. Adresy URL
    • W moim przypadku nie ma korzenia API. Powinienem mieć tylko adresy URL, aby uzyskać różne wyniki obliczeń (kalkulator z parametrami różnic).
    • Dodaj wywołujące format_suffix_patterns do przeglądania interfejsu API.

Przegapiłem coś? Czy podejście jest ogólnie poprawne?


To podejście jest poprawne i wydaje mi się bardziej eleganckie niż przyjęta odpowiedź (dane wyników zawarte w typie wyniku wielokrotnego użytku). Ale ostatecznie jest to głównie kwestia osobistych preferencji i oba podejścia działają.
zepp.lee

Odpowiedzi:


157

Django-rest-framework działa dobrze nawet bez wiązania go z modelem. Twoje podejście brzmi dobrze, ale uważam, że możesz przyciąć niektóre kroki, aby wszystko działało.

Na przykład struktura REST zawiera kilka wbudowanych programów renderujących. Po wyjęciu z pudełka może zwracać JSON i XML konsumentowi API. Możesz również włączyć YAML, po prostu instalując wymagany moduł Pythona. Django-rest-framework wyświetli każdy podstawowy obiekt, taki jak dict, list i tuple, bez dodatkowej pracy z Twojej strony.

W zasadzie wystarczy utworzyć funkcję lub klasę, która pobiera argumenty, wykonuje wszystkie wymagane obliczenia i zwraca wyniki w postaci krotki do widoku REST api. Jeśli JSON i / lub XML pasuje do Twoich potrzeb, django-rest-framework zajmie się serializacją za Ciebie.

W takim przypadku można pominąć kroki 2 i 3 i po prostu użyć jednej klasy do obliczeń i jednej do prezentacji konsumentowi interfejsu API.

Oto kilka fragmentów, które mogą Ci pomóc:

Zwróć uwagę, że nie testowałem tego. To tylko przykład, ale powinno działać :)

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

Widok 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

Twój adres 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'),
)

Ten kod powinien wyświetlać listę list podczas uzyskiwania dostępu do http://example.com/api/v1.0/resource/?format=json . Jeśli za pomocą przyrostka można zastąpić ?format=jsonz .json. Możesz także określić kodowanie, które chcesz przywrócić, dodając "Content-type"lub "Accept"do nagłówków.

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

Mam nadzieję, że to ci pomoże.


2
Cześć Gabriel! Dziękuję za Twoją odpowiedź! Zrealizowałem już to, czego potrzebuję, zgodnie z moim planem. Działa w porządku! Użyłem serializatora dla lepszego wyjścia json.
Zakhar

3
Próbowałem postępować zgodnie z tą sugestią, ale otrzymuję: „Nie można zastosować uprawnień DjangoModelPermissions do widoku, który nie ma właściwości .modellub .queryset.”. Wypróbowałem dokładnie podany przykład. Czy to może być coś z najnowszą wersją django-rest-framework?
Orlando,

Ten przykład został napisany jakiś czas temu. Od tamtej pory nie miałem okazji ponownie pracować z Django. ale możesz znaleźć tu coś przydatnego: django-rest-framework.org/api-guide/routers
Gabriel Samfira

1
Ten przykład jest dokładnie tym, czego potrzebowałem, aby potrzebować usługi, która wykonuje pewne operacje bez serializatora innego niż model!
Khalil TABBAL

@Orlando: Zobacz tutaj, jak zaimplementować logikę uprawnień specyficzną dla widoku innego niż model z djang-restframework 3: stackoverflow.com/a/34040070/640916
djangonaut

-1

W pliku urls.py wymagana jest funkcja login_required

from django.contrib.auth.decorators import login_required

jeśli to tylko komentarz zamiast odpowiedzi, rozważ skorzystanie z add a commentsesji
lucascavalcante
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.