Django REST framework: немодельный сериализатор

158

Я новичок в Django REST Framework и мне нужен ваш совет. Я занимаюсь разработкой веб-сервиса. Служба должна предоставлять интерфейс REST другим службам. Интерфейс REST, который мне нужно реализовать, не работает с моими моделями напрямую (я имею в виду операции get, put, post, delete). Вместо этого он предоставляет другим службам некоторые результаты расчетов. По запросу мой сервис выполняет некоторые вычисления и просто возвращает результаты обратно (не сохраняет результаты в своей собственной базе данных).

Ниже мое понимание того, как этот интерфейс REST может быть реализован. Поправь меня, если я ошибаюсь.

  1. Создать класс, который делает вычисления. Назовите его «CalcClass». CalcClass использует модели в своей работе.
    • Параметры, необходимые для расчетов, передаются в конструктор.
    • Реализуйте операцию calc. Возвращает результаты как ResultClass.
  2. Создать ResultClass.
    • Получено от объекта.
    • Он имеет только атрибуты, содержащие результаты вычислений.
    • Одна часть результатов вычислений представлена ​​как кортеж кортежей. Как я понимаю, для дальнейшей сериализации было бы лучше реализовать отдельный класс для этих результатов и добавить список таких объектов в ResultClass.
  3. Создать сериализатор для ResultClass.
    • Производные от сериализаторов. Сериализатор.
    • Результаты вычислений доступны только для чтения, поэтому для полей используйте в основном класс Field, а не специализированные классы, такие как IntegerField.
    • Я не должен включать метод save () ни в ResultClass, ни в Serializer, потому что я не собираюсь хранить результаты (я просто хочу вернуть их по запросу).
    • Impl сериализатор для вложенных результатов (помните кортеж из упомянутых выше кортежей).
  4. Создать представление, чтобы вернуть результаты расчета.
    • Получено из APIView.
    • Нужно просто получить ().
    • В get () создайте CalcClass с параметрами, полученными из запроса, вызовите его calc (), получите ResultClass, создайте Serializer и передайте ему ResultClass, верните Response (serializer.data).
  5. URL-адрес
    • В моем случае нет корня API. Мне просто нужно иметь URL-адреса, чтобы получить различные результаты вычислений (calc с diff-параметрами).
    • Добавьте вызов format_suffix_patterns для просмотра API.

Я что-то пропустил? Правильный ли подход в целом?

Захара
источник
Этот подход является правильным и для меня на самом деле выглядит более элегантно, чем принятый ответ (данные результатов, инкапсулированные в тип результатов результатов многократного использования). Но, в конце концов, это в основном вопрос личных предпочтений, и оба подхода делают свою работу.
Zepp.lee

Ответы:

157

Django-rest-framework работает хорошо даже без привязки к модели. Ваш подход звучит хорошо, но я считаю, что вы можете обрезать некоторые шаги, чтобы все заработало.

Например, инфраструктура отдыха поставляется с несколькими встроенными средствами рендеринга. Из коробки он может вернуть JSON и XML потребителю API. Вы также можете включить YAML, просто установив необходимый модуль Python. Django-rest-framework выведет любой базовый объект, такой как dict, list и tuple, без дополнительной работы с вашей стороны.

Таким образом, в основном вам нужно только создать функцию или класс, который принимает аргументы, выполняет все необходимые вычисления и возвращает результаты в виде кортежа в представление REST API. Если JSON и / или XML соответствуют вашим потребностям, django-rest-framework позаботится о сериализации для вас.

В этом случае вы можете пропустить шаги 2 и 3 и просто использовать один класс для вычислений и один для представления потребителю API.

Вот несколько фрагментов, которые могут вам помочь:

Обратите внимание, что я не проверял это. Это только в качестве примера, но это должно работать :)

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

ОТДЫХ:

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

Ваш 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'),
)

Этот код должен выводить список списков при доступе к http://example.com/api/v1.0/resource/?format=json . Если вы используете суффикс, вы можете заменить его ?format=jsonна .json. Вы также можете указать кодировку, которую хотите получить, добавив "Content-type"или "Accept"к заголовкам.

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

Надеюсь, что это помогает вам.

Габриэль Самфира
источник
2
Привет Габриэль! Спасибо за ваш ответ! Я уже реализовал то, что мне нужно в соответствии с моим планом. Работает отлично! Я использовал сериализатор для лучшего вывода JSON.
Захар
3
Я пытался следовать этому предложению, но я получаю: «Не удается применить DjangoModelPermissions к представлению, которое не имеет .modelили .querysetсвойство.». Я попробовал точный пример при условии. Может ли это быть что-то с недавней версией django-rest-framework?
Орландо
Этот пример был написан некоторое время назад. С тех пор у меня не было возможности снова работать с Джанго. но вы можете найти что-то полезное здесь: django-rest-framework.org/api-guide/routers
Габриэль Самфира
1
Этот пример как раз то, что мне нужно для моей потребности - это сервис, который выполняет некоторые операции без не модельного сериализатора!
Халил Таббал
@ Orlando: Посмотрите здесь, как реализовать логику разрешений, специфичную для немодельного представления, с помощью djang-restframework 3: stackoverflow.com/a/34040070/640916
djangonaut
-1

В файле urls.py функция login_required требует

from django.contrib.auth.decorators import login_required
ymorvan
источник
если это только комментарий, а не ответ, рассмотрите возможность использования add a commentсессии
lucascavalcante