1. ホーム
  2. django

[解決済み] Django REST フレームワーク: 非モデルシリアライザー

2022-04-21 14:56:13

質問

Django RESTフレームワークの初心者ですが、アドバイスをお願いします。私はウェブサービスを開発しています。このサービスは、他のサービスにRESTインタフェースを提供する必要があります。私が実装する必要があるRESTインターフェースは、私のモデルで直接動作しません(私は、取得、配置、投稿、削除の操作を意味します)。その代わり、他のサービスに計算結果を提供します。私のサービスはリクエストに応じて計算を行い、その結果を返すだけです(結果を自身のデータベースに保存しません)。

以下は、そのRESTインターフェースがどのように実装され得るかについての私の理解です。もし間違っていたら、訂正してください。

  1. 計算を行うクラスを作成します。名前は「CalcClass」とします。CalcClassは、その作業でモデルを使用します。

    • 計算に必要なパラメータはコンストラクタに渡されます。
    • calc演算を実装する。結果は'ResultClass'として返す。
  2. ResultClassを作成します。

    • オブジェクトから派生したもの。
    • ただ、計算結果を含む属性しか持っていない。
    • 計算結果の一部は、タプルのタプルとして表現されます。私の理解では、これらの結果のために別のクラスを実装し、ResultClassにそのようなオブジェクトのリストを追加することは、さらなるシリアライズのために良いことだと思われます。
  3. ResultClass用のSerializerを作成します。

    • serializers.Serializerから派生したものです。
    • 計算結果は読み取り専用なので、フィールドには IntegerField などの特殊なクラスではなく、ほとんど Field クラスを使用してください。
    • 私は結果を保存するつもりはない(私は要求に応じてそれらを返したいだけ)ので、私はResultClassとSerializerの両方でsave()メソッドを暗黙させないでください。
    • ネストされた結果に対してシリアライザーをインポートする(上記のタプルのタプルを思い出してください)。
  4. 計算結果を返すためのViewを作成します。

    • APIViewから派生させます。
    • get()だけが必要。
    • get() で、リクエストから取得したパラメータで CalcClass を作成し、その calc() を呼び出して ResultClass を取得し、Serializer を作成して ResultClass を渡し、Response(serializer.data) を返しています。
  5. URL

    • 私の場合、apiのルートはありません。様々なcalcの結果(異なるパラメータを持つcalc)を得るためのURLを持っていればいいのです。
    • apiブラウジングのためにformat_suffix_patternsを呼び出すことを追加。

何か見落としがあったのでしょうか?一般的にこのアプローチは正しいのでしょうか?

どのように解決するのですか?

Django-rest-frameworkは、モデルに結びつけなくてもうまく動きます。あなたのアプローチは大丈夫そうですが、私はあなたがすべてを動作させるためにいくつかのステップを削減することができると信じています。

例えば、restフレームワークにはいくつかの組み込みレンダラーが用意されています。そのままでは、API コンシューマーに JSON と XML を返すことができます。必要な Python モジュールをインストールするだけで、YAML を有効にすることもできます。Django-rest-frameworkは、dict、list、tupleのような基本的なオブジェクトを、あなたの側で特別な作業をすることなく出力します。

つまり、基本的には引数を受け取り、必要な計算を行い、その結果をREST APIビューにタプルとして返す関数またはクラスを作成するだけです。もし JSON や XML があなたのニーズに合うなら、 django-rest-framework があなたのためにシリアライズを引き受けます。

この場合、ステップ2と3をスキップして、1つのクラスを計算用と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
  ]
]

これがあなたのお役に立つことを願っています。