【问题标题】:Django REST framework: how to wrap the response with extra fields .... and supply the current response in data fieldDjango REST框架:如何用额外的字段包装响应......并在数据字段中提供当前响应
【发布时间】:2020-05-29 07:52:13
【问题描述】:

所以,我有以下几点:

class ObjectViewSet(
    mixins.CreateModelMixin,
    mixins.ListModelMixin,
    mixins.RetrieveModelMixin,
    mixins.DestroyModelMixin,
    viewsets.GenericViewSet
):
    """
    REST API endpoints for Objects.
    """
    serializer_class = ObjectSerializer
    queryset = Object.objects.all()

这会返回一个列表 GET 请求:

[
    {
        "uuid": "787573a2-b4f1-40df-9e3a-8555fd873461",
    },
    {
        "uuid": "2ab56449-1be1-47d7-aceb-a9eaefa49665",
    }
]

但是,我怎样才能稍微改变这个 mixins 的响应,使其类似于以下内容:

{
    success: true,
    message: 'Some Extra Useful Message',
    data: [
        {
             "uuid": "787573a2-b4f1-40df-9e3a-8555fd873461",
        },
        {
             "uuid": "2ab56449-1be1-47d7-aceb-a9eaefa49665",
        }
    ]
}

这可能吗,还是我应该只编写自己的自定义端点 Response() 而不使用 DRF 的 mixins 功能?

所以,本质上,切换自定义:

Response(data, status=None, template_name=None, headers=None, content_type=None)

收件人:


response = {
    'success': true,
    'message': 'Some Extra Useful Message',
    'data': serializer.data
}

Response(response, status=None, template_name=None, headers=None, content_type=None)

【问题讨论】:

标签: django django-rest-framework


【解决方案1】:

经过长时间的研究,我发现这很有用且最适合使用。对于此类用例,必须参考此documentation。在您的情况下,您可以执行以下操作 -

声明一个类renderer.py

from rest_framework.renderers import JSONRenderer
from rest_framework.utils import json


class JSONResponseRenderer(JSONRenderer):
    # media_type = 'text/plain'
    # media_type = 'application/json'
    charset = 'utf-8'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        response_dict = {
            'status': 'failure',
            'data': data,
            'message': '',
        }
        data = response_dict
        return json.dumps(data)

更新您的 settings.py

REST_FRAMEWORK = {
    # Other code
    'DEFAULT_RENDERER_CLASSES': (
        '<app-name>.renderer.JSONResponseRenderer',
    )
}

更新您的 ViewSet 类

class YourViewSet(viewsets.ModelViewSet):
    # Other code
    renderer_classes = [JSONResponseRenderer]

一切就绪!另请参阅此post 更多。

【讨论】:

    【解决方案2】:

    您可以使用Middelwares 处理这种响应格式。如果基于状态码你有一个固定的响应格式,那就写一个中间件。

    class ResponseFormatMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            response = self.get_response(request)
            try:
                if (not getattr(response, 'error', False)) and (isinstance(response.data, dict) or isinstance(response.data, list)):
                    response.data = {'success': True, 'message':'some message','data': response.data}
            except AttributeError:
                pass
            return response
    

    中间件在CustomMiddleware模块中写成middleware.py,然后添加

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'CustomMiddleware.middleware.ResponseFormatMiddleware', # Added this line
    ]
    

    settings.py 文件中。

    【讨论】:

    • 这没关系 - 在中间件中进行,但并不理想。理想情况下,我认为响应类需要稍微覆盖。我仍然会投赞成票,因为它部分有效,我感谢您的努力。
    • 好的。我将检查另一种方法,即覆盖 rest_framework 的响应类。
    猜你喜欢
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 2018-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多