Django RESTフレームワークのResponse
クラスを上書きして、応答ディクショナリディクショナリに3つのパラメーターmessage
、status
およびdata
こんにちは親愛なる
DRF
の_Response Class
_を変更して、2つの追加パラメーター(メッセージ、ステータス)とDRFシリアライザーによって提供されるデータを渡すようにしています。 message
Done
、_User Created
_などのメッセージを渡し、status
fail
またはsuccess
などのメッセージを渡しますメッセージとこのメッセージは、フロントエンドとバックエンド間の特別なコードを予約するのに役立ちます。
このパラメーターを設定しない場合は、空の文字またはnullの結果をクライアント側に返します
例えば成功モードで:
_{
'data': {
'value_one': 'some data',
'value_two': 'some data',
'value_three': [
'value', 'value', 'value'
],
},
}
'message': 'Done',
'status': 'success',
}
_
失敗モードでは:
_{
'data': ['any error message raise by serializer',]
'message': 'Create User Failed',
'status': 'failure',
}
_
私は自分の質問について検索し、この解決策を見つけました:
クラスで_DRF Response Class
_を継承して___init__
_メソッドを上書きし、このメソッドでメッセージ、データ、ステータスを取得して、独自のデータ構造を持つ親のinitを呼び出し、このレスポンシブクラスを使用する場合このような私の機能では実装:
_from rest_framework.response import Response
class Response(Response):
def __init__(self, data=None, message=None, data_status=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None):
data_content = {
'status': data_status,
'data': data,
'message': message,
}
super(Response, self).__init__(
data=data_content,
status=status,
template_name=template_name,
headers=headers,
exception=exception,
content_type=content_type
)
_
成功モードの呼び出し:
_return Response(data=serializer.data, message='Done', data_status='success', status=200)
_
失敗モードの呼び出し:
_return Response(data=serializer.errors, message='Create User Failed', data_status='failure', status=400)
_
このソリューションでproblem
を使用したすべてのビュークラスで独自のResponseクラスを使用します。_GenericViews Class
_を使用する場合、ビューのロジックで使用したすべてのhttpメソッドを上書きし、独自のクラスを呼び出す必要があります乾燥!!
そして私が見つけた他の解決策。シリアル化された層では、Serializer
クラスに抽象メソッドdef to_representation(self, instance):
があり、ModelSerializer
クラス継承Serializer
などの他のクラスに実装し、このメソッドをシリアライザクラスを使用して、ビューレイヤに送信する前にデータを再フェッチし、次のように実装します。
_from collections import OrderedDict
class OurSerializer(serializer.ModelSerializer):
....
def to_representation(self, instance):
data = super(serializers.ModelSerializer, self).to_representation(instance)
result = OrderedDict()
result['data'] = data
result['message'] = 'Done'
result['status'] = 'sucssed'
return result
_
この解決策は上記の問題を解決しますが、再び2つの問題があります
1つ目:入れ子のシリアライザーを使用していて、シリアライザークラスでこの関数を上書きした場合、次のような不良データが返されます。
_{
'data': {
'value_one': 'some data',
'value_two': 'some data',
'value_three': {
'data': [
'value', 'value', 'value'
],
'message': 'Done',
'status': 'sucssed',
},
}
'message': 'Done',
'status': 'sucssed',
}
_
およびmessage
とstatus
が繰り返され、構造がクライアントに不適切です
2つ目:このモードでは例外を処理できず、このようなミドルウェアクラスだけで例外を処理する方法 DRF Exception Handling であり、これは役に立たない方法であり、発生したエラーのタイプを処理できませんビューで快適な個別のmessage
とstatus
を生成します。
この質問に別の良い解決策がある場合は、私を案内してください。
ありがとう:)
これを解決するためのベストプラクティス(DRFが提案した)は、「レンダラー」クラスを使用することです。レンダラーは構造化された応答を操作して返します。
Djangoは テンプレートレンダラー のようなレンダラーを使用し、DRFはこの機能にメリットをもたらし、 APIレンダラー を提供します。
これを行うには、このようなレンダラーをパッケージで提供できます(例:app_name.renderers.ApiRenderer
):
from rest_framework.renderers import BaseRenderer
from rest_framework.utils import json
class ApiRenderer(BaseRenderer):
def render(self, data, accepted_media_type=None, renderer_context=None):
response_dict = {
'status': 'failure',
'data': {},
'message': '',
}
if data.get('data'):
response_dict['data'] = data.get('data')
if data.get('status'):
response_dict['status'] = data.get('status')
if data.get('message'):
response_dict['message'] = data.get('message')
data = response_dict
return json.dumps(data)
そして、設定ファイルで:
REST_FRAMEWORK = {
...
'DEFAULT_RENDERER_CLASSES': (
'app_name.renderers.ApiRenderer',
),
...
}
このアクションにより、DRF汎用ビューを拡張するすべてのビューがレンダラーを使用します。設定をオーバーライドする必要がある場合は、ジェネリックビュークラスにはrenderer_classes
属性を、APIビュー関数には@renderer_classes
デコレータを使用できます。
オーバーライドする包括的なレンダラークラスは、<virtualenv_dir>/lib/python3.6/site-packages/rest_framework/renderers.py
にあります。
カスタムレスポンスミドルウェアを作成しようとしましたか?
class ResponseCustomMiddleware(MiddlewareMixin):
def __init__(self, *args, **kwargs):
super(ResponseCustomMiddleware, self).__init__(*args, **kwargs)
def process_template_response(self, request, response):
if not response.is_rendered and isinstance(response, Response):
if isinstance(response.data, dict):
message = response.data.get('message', 'Some error occurred')
if 'data' not in response.data:
response.data = {'data': response.data}
response.data.setdefault('message', message)
# you can add you logic for checking in status code is 2** or 4**.
data_status = 'unknown'
if response.status_code // 100 == 2:
data_status = 'success'
Elif response.status_code // 100 == 4:
data_status = 'failure'
response.data.setdefault('data_status', data_status)
return response
設定にミドルウェアを追加します。
MIDDLEWARE = [
# you all middleware here,
'common.middleware.ResponseCustomMiddleware',
]
したがって、次のようにResponse
を返すことができます。
data = {'var1': 1, 'var2': 2}
return Response({'data': data, 'message': 'This is my message'}, status=status.HTTP_201_CREATED)
応答は次のようになります。
{
"data": [
{
"var1": 1,
"var2": 2
}
],
"message": "This is my message",
"data_status": "success"
}
これが私が問題を解決する方法です。それが役に立てば幸い
_ def custom_response(data, code=None, message=None):
if not code and not message:
code = SUCCESSFUL_CODE
message = SUCCESSFUL_MESSAGE
return Response(OrderedDict([
('code', code),
('message', message),
('results', data)
]))
_
これでビュー関数になりました。非常に簡単にしたいが、レスポンスをカスタマイズできますreturn custom_response(data=..,message=...,code=...)