Django RESTフレームワーク:非モデルシリアライザー


158

私はDjango RESTフレームワークの初心者であり、あなたのアドバイスが必要です。Webサービスを開発しています。サービスは他のサービスへのRESTインターフェースを提供する必要があります。私が実装する必要のあるRESTインターフェースは、モデルで直接機能していません(つまり、取得、書き込み、投稿、削除操作を意味します)。代わりに、他のサービスにいくつかの計算結果を提供します。リクエストに応じて、私のサービスはいくつかの計算を行い、結果を返します(結果を独自のデータベースに保存しません)。

以下は、RESTインターフェースを実装する方法についての私の理解です。私が間違っているなら、私を訂正してください。

  1. 計算を行うクラスを作成します。「CalcClass」という名前を付けます。CalcClassは作業にモデルを使用します。
    • 計算に必要なパラメーターはコンストラクターに渡されます。
    • 計算操作を実装します。結果は「ResultClass」として返されます。
  2. ResultClassを作成します。
    • オブジェクトから派生。
    • 計算結果を含む属性のみが含まれます。
    • 計算結果の一部は、タプルのタプルとして表されます。私が理解しているように、これらの結果用に別のクラスを実装し、そのようなオブジェクトのリストをResultClassに追加することは、さらなるシリアライゼーションにとってより良いでしょう。
  3. ResultClassのシリアライザを作成します。
    • serializers.Serializerから派生。
    • 計算結果は読み取り専用であるため、IntegerFieldなどの特殊なクラスではなく、ほとんどの場合フィールドのFieldクラスを使用します。
    • 結果を保存するつもりはないので、ResultClassにもSerializerにもsave()メソッドを実装しないでください(リクエストに応じて結果を返したいだけです)。
    • ネストされた結果のImplシリアライザー(上記のタプルのタプルを忘れないでください)。
  4. 計算結果を返すビューを作成します。
    • APIViewから派生します。
    • get()だけが必要です。
    • get()で、リクエストから取得したparamsでCalcClassを作成し、そのcalc()を呼び出し、ResultClassを取得し、Serializerを作成して、それにResultClassを渡し、Response(serializer.data)を返します。
  5. URL
    • 私の場合、APIルートはありません。さまざまな計算結果(diff paramsを使用した計算)を取得するには、URLが必要です。
    • APIブラウジング用の呼び出しformat_suffix_patternsを追加します。

私は何か見落としてますか?アプローチは一般的に正しいですか?


このアプローチは正しく、実際には、受け入れられた回答(再利用可能な結果タイプにカプセル化された結果データ)よりもエレガントに見えます。しかし結局のところ、これは主に個人的な好みの問題であり、どちらのアプローチでも機能します。
zepp.lee 2019

回答:


157

Django-rest-frameworkは、モデルに関連付けなくてもうまく機能します。あなたのアプローチは大丈夫に聞こえますが、すべてを機能させるためにいくつかのステップをトリミングできると思います。

たとえば、残りのフレームワークにはいくつかの組み込みレンダラーが付属しています。デフォルトでは、JSONとXMLをAPIコンシューマーに返すことができます。必要なPythonモジュールをインストールするだけでYAMLを有効にすることもできます。Django-rest-frameworkは、辞書、リスト、タプルなどの基本的なオブジェクトを出力します。ユーザー側で追加の作業を行う必要はありません。

したがって、基本的には、引数を取り、必要な計算をすべて実行し、その結果をタプルでREST APIビューに返す関数またはクラスを作成するだけで済みます。JSONまたはXML、あるいはその両方がニーズに合う場合は、django-rest-frameworkがシリアル化を処理します。

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

これがお役に立てば幸いです。


2
ガブリエルこんにちは!お返事ありがとうございます!私はすでに私の計画に従って必要なものを実装しました。正常に動作します!json出力を改善するためにシリアライザを使用しました。
ザカー

3
私はこの提案に従いましたが、「.modelまたはのないビューにDjangoModelPermissionsを適用できません。」というメッセージが表示されました.queryset。私は提供された正確な例を試しました。django-rest-frameworkの最近のバージョンで何かできるのでしょうか?
オーランド

この例は少し前に書かれました。それ以来、私は再びDjangoで作業する機会がありませんでした。しかし、あなたはここで何か役に立つものを見つけるかもしれません:django-rest-framework.org/api-guide/routers
Gabriel Samfira

1
この例は、私が必要とするものであり、非モデルのシリアライザなしでいくつかの操作を行うサービスです!
Khalil TABBAL、2015

@Orlando:djang-restframework 3を使用して非モデルビューに固有の権限ロジックを実装する方法については、こちらをご覧ください: stackoverflow.com/a/34040070/640916
djangonaut

-1

urls.pyでは、login_required関数が必要です

from django.contrib.auth.decorators import login_required

回答ではなくコメントのみの場合は、add a commentセッションの使用を検討してください
lucascavalcante
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.