如何在Django Rest Framework(DRF)中覆盖Response类? [英] how overwrite Response class in django rest framework ( DRF )?

查看:113
本文介绍了如何在Django Rest Framework(DRF)中覆盖Response类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想覆盖Django rest框架的 Response 类,以便响应返回响应字典包含三个参数 message 状态数据



您好,亲爱的

>

我尝试在 DRF 中更改 Response Class 参数(消息,状态)加上DRF串行器提供的数据。 消息传递消息,例如完成用户创建等和状态传递诸如失败成功之类的消息消息,该消息对于在前端和后端之间保留特殊代码很有用。



如果不设置此参数,我想返回空字符或返回空值给客户端



例如在成功模式下:

  {
'数据:{
'value_one':'一些数据',
'value_two':'一些数据',
'value_three':[
'value','value' ,'value'
],
},
}
'message':'Done',
'status':'success',
}

并处于故障模式:

  {
'data':['任何由序列化程序引发的错误消息',]
'message':'创建用户失败',
'status': '失败',
}

我搜索了我的问题并找到了以下解决方案:



如果我继承了 DRF响应类在我的课程中,覆盖 __ init __ 方法,并在此方法中获取消息,数据和状态,并使用自己的数据结构调用父级的 init 并使用此方法像我这样的工具中的响应类:

  from rest_framework.response import响应


类响应(响应):

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':消息,
}
super(响应,自我).__ init __(
data = data_content,
status = status,
template_name = template_na我,
标头=标头,
异常=例外,
content_type = content_type

在成功模式下调用:

 返回响应(data = serializer.data,message ='完成',data_status ='成功',状态= 200)

在故障模式下调用:

 返回响应(data = serializer.errors,message ='Create User Failed',data_status ='failure',status = 400)

并在所有视图类
中使用自己的Response类,我们遇到了问题在此解决方案中:如果我们使用 GenericViews类必须覆盖我们在视图逻辑中使用的所有http方法并调用自己的类,这就是 DRY !!






我发现了其他解决方案。在序列化层中,我们在 Serializer 类中具有抽象方法 def to_representation(self,instance):,并在其他类中实现如 ModelSerializer 类继承 Serializer ,如果我们在序列化器类中覆盖此方法并在发送到视图层之前重新获取数据,实现如下:

 从集合中导入OrderedDict 

类OurSerializer(serializer.ModelSerializer):

....

def to_representation(self,instance):
data = super(serializers.ModelSerializer,self).to_representation(instance)
结果= OrderedDict()
结果['data'] =数据
结果['message'] ='完成'
结果['status'] ='成功'
返回结果

此解决方案可以解决上述问题,但我们又遇到了两个问题



一个:如果我们使用嵌套的序列化程序,并且已经在序列化程序类返回错误数据,例如:

  {
'data':{
'value_one':'一些数据,
'value_two':'一些数据',
'value_three':{
'data':[
'value','value','value'
],
'message':'Done',
'status':'sucssed',
},
}
'message':'完成,
状态:成功,
}

消息状态重复出现,并且对客户而言结构不佳



和两个:我们无法在这种模式下处理异常,而只能通过像这样的中间件类来处理异常 DRF异常处理,这不是有用的方法,我们无法处理视图中发生的任何类型的错误并生成舒适的单独 message 状态



如果该问题还有另一个好的解决方案,请指导我。



谢谢:)

解决方案

要解决此问题,最佳实践(DRF提出)是使用渲染器类。渲染器操纵并返回结构化响应。



Django使用的渲染器如模板渲染器和DRF受益于此功能,并提供 API渲染器。。 p>

要这样做,可以在程序包中提供这样的渲染器(例如 app_name.renderers.ApiRenderer ):

 从rest_framework.renderers导入BaseRenderer 
从rest_framework.utils导入json


ApiRenderer(BaseRenderer)类:

def render(自身,数据,accepted_media_type =无,renderer_context =无):
response_dict = {
'status':'failure',
'数据':{},
'消息':'',
}
如果data.get('data'):
response_dict ['data'] = data.get('data')
如果data.get('status'):
响应se_dict ['status'] = data.get('status')
如果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 属性用于通用视图类,将 @renderer_classes 装饰器用于api视图功能。



< virtualenv_dir> /lib/python3.6/site-packages/rest_framework/renderers.py中提供了要覆盖的全面渲染器类。


I want to overwrite Response class of django rest framework so that response back responsive dictionary contain three parameter message, status and data

Hello dears all

I try to change Response Class in DRF to pass two extra parameter ( message, status ) plus data provide by DRF serializer. message pass the message like Done, User Created or etc and status pass the message like fail or success or etc message and this message useful for reserve special code between frontend and backend.

I want to if don't set this parameter return empty character or null result back to client side

for example in success mode:

{
    'data': {
        'value_one': 'some data',
        'value_two': 'some data',
        'value_three': [
                'value', 'value', 'value'
            ],
        },
    }
    'message': 'Done',
    'status': 'success',
}

and in failure mode:

{
    'data': ['any error message raise by serializer',]
    'message': 'Create User Failed',
    'status': 'failure',
}

I search about my question and found this solution:

if i inheritance DRF Response Class in my class and overwrite __init__ method and get message, data and status in this method and call init of parent with own data structure and use this responsive class in my functionality like this implement:

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
        )

in success mode call:

return Response(data=serializer.data, message='Done', data_status='success', status=200)

in failure mode call:

return Response(data=serializer.errors, message='Create User Failed', data_status='failure', status=400)

and use own Response class in all views class we had problem in this solution: if we use GenericViews Class must be overwrite all http methods we used in view's logic and call own class and this is DRY!!


and other solution i found. in serialized layer, we have abstract method def to_representation(self, instance): in Serializer class and implement in other class like ModelSerializer class inheritance Serializer and if we overwrite this method in our serializer class and re fetch data before send to view layer, implement like:

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

this solution solve above problem but we have two problem again

one: if we use nested serializer and we had overwrite this function in serializer class return bad data like:

{
    'data': {
        'value_one': 'some data',
        'value_two': 'some data',
        'value_three': {
            'data': [
                'value', 'value', 'value'
            ],
            'message': 'Done',
            'status': 'sucssed',
        },
    }
    'message': 'Done',
    'status': 'sucssed',
}

and message and status repeated and structure not pretty for client

and two: we cant handle exception in this mode and just way to handle exception just with middleware class like this DRF Exception Handling and this isn't useful way, we can't handle any type of error occurs in view and generate comfortable separate message and status.

IF there's another good solution to this question, please guide me.

thanks :)

解决方案

To resolve this, best practice (that DRF has proposed) is to use 'renderer' classes. A renderer manipulates and returns structured response.

Django uses renderers like Template Renderer and DRF benefits this feature and provides API Renderers.

To do so, you could provide such this renderer in a package (e.g. 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)

And then in your settings file:

REST_FRAMEWORK = {
    ...
    'DEFAULT_RENDERER_CLASSES': (
        'app_name.renderers.ApiRenderer',
    ),
    ...
}

By this action all views that extend DRF generic views will use renderer. If you needed to override setting you can use renderer_classes attribute for generic view classes and @renderer_classes decorator for api view functions.

A comprehensive renderer class to override is available at <virtualenv_dir>/lib/python3.6/site-packages/rest_framework/renderers.py.

这篇关于如何在Django Rest Framework(DRF)中覆盖Response类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆