Django REST框架:非模型序列化器


158

我是Django REST框架的初学者,需要您的建议。我正在开发Web服务。该服务必须提供与其他服务的REST接口。我需要实现的REST接口不能直接与我的模型一起使用(我的意思是获取,放置,发布,删除操作)。相反,它为其他服务提供了一些计算结果。根据请求,我的服务会进行一些计算,只是将结果返回(不将结果存储在自己的数据库中)。

以下是我对如何实现REST接口的理解。纠正我,如果我错了。

  1. 创建进行计算的类。将其命名为“ CalcClass”。CalcClass在其工作中使用模型。
    • 计算所需的参数传递给构造函数。
    • 实现calc操作。它以“ ResultClass”的形式返回结果。
  2. 创建ResultClass。
    • 源自对象。
    • 它仅具有包含calc结果的属性。
    • 计算结果的一部分表示为元组的元组。据我了解,最好进一步序列化为这些结果实现一个单独的类,并将此类对象的列表添加到ResultClass中。
  3. 为ResultClass创建序列化器。
    • 从序列化器派生。
    • calc结果是只读的,因此主要将Field类用于字段,而不是专门的类(例如IntegerField)。
    • 我不应该在ResultClass或Serializer上都使用save()方法,因为我不会存储结果(我只想根据要求返回它们)。
    • 用于嵌套结果的Impl序列化器(请记住上面提到的元组的元组)。
  4. 创建视图以返回计算结果。
    • 从APIView派生。
    • 只需要get()。
    • 在get()中创建具有从请求中检索到的参数的CalcClass,调用其calc(),获取ResultClass,创建Serializer并将ResultClass传递给它,返回Response(serializer.data)。
  5. 网址
    • 我的情况下没有api根。我应该只有URL才能获得各种计算结果(带diff参数的计算)。
    • 添加调用format_suffix_patterns进行api浏览。

我错过了什么?该方法总体上正确吗?


这种方法是正确的,并且对我来说,实际上看起来比接受的答案更优雅(结果数据封装在可重用的结果类型中)。但归根结底,这主要是个人喜好问题,这两种方法都能胜任。
zepp.lee

Answers:


157

即使没有将Django-rest-framework绑定到模型,它也可以很好地工作。您的方法听起来不错,但我相信您可以减少一些步骤,以使所有工作正常进行。

例如,rest框架带有一些内置的渲染器。开箱即用,它可以将JSON和XML返回给API使用者。您还可以通过仅安装所需的python模块来启用YAML。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

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

您的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输出。
Zakhar

3
我试图按照此建议,但我得到:“在不具有视图不能适用DjangoModelPermissions .model.queryset。财产”。我已经尝试了提供的确切示例。最新版本的django-rest-framework可能有用吗?
奥兰多

这个例子已经写了一段时间了。从那以后,我再也没有机会与Django合作。但您可能会在这里找到一些有用的信息:django-rest-framework.org/api-guide/routers
Gabriel Samfira 2014年

1
这个示例正是我所需要的,它是一项无需使用非模型序列化程序即可执行某些操作的服务!
哈利勒·塔伯

@Orlando:在这里看看如何使用djang-restframework实现特定于非模型视图的权限逻辑3: stackoverflow.com/a/34040070/640916
djangonaut 2015年

-1

在urls.py中,函数login_required需要

from django.contrib.auth.decorators import login_required

如果那只是评论而不是答案,请考虑使用add a comment会议
lucascavalcante
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.