zoukankan      html  css  js  c++  java
  • 二次封装Response类 | 视图类传递参数给序列化类context

    二次封装Response类

    源码:

    class Response(SimpleTemplateResponse):
        """
        An HttpResponse that allows its data to be rendered into
        arbitrary media types.
        """
    
        def __init__(self, data=None, status=None,
                     template_name=None, headers=None,
                     exception=False, content_type=None):
            """
            Alters the init arguments slightly.
            For example, drop 'template_name', and instead use 'data'.
    
            Setting 'renderer' and 'media_type' will typically be deferred,
            For example being set automatically by the `APIView`.
            """
            super().__init__(None, status=status)
    
            if isinstance(data, Serializer):
                msg = (
                    'You passed a Serializer instance as data, but '
                    'probably meant to pass serialized `.data` or '
                    '`.error`. representation.'
                )
                raise AssertionError(msg)
    
            self.data = data
            self.template_name = template_name
            self.exception = exception
            self.content_type = content_type
    
            if headers:
                for name, value in headers.items():
                    self[name] = value
            ......

     分析

    """
    Response({
        'status': 0,
        'msg': 'ok',
        'results': [],
        'token': ''  # 有这样的额外的key-value数据结果
    },status=http_status,headers=headers,exception=True|False)
    
    APIResponse() => Response({'status': 0,'msg': 'ok'})
    """

     封装后

    from rest_framework.response import Response
    
    class APIResponse(Response):
        def __init__(self, data_status=0, data_msg='ok', results=None, http_status=None, headers=None, exception=None, **kwargs):
            # data的初始状态: 状态码与状态信息
            data = {
                'status': data_status,
                'msg':data_msg
            }
            # data的响应数据体: results (其可能是False,0等数据, 这些数据某些情况下也会作为合法数据返回)
            if results is not None:
                data['results'] = results
            # data响应的其他内容:
            # if kwargs is not None:
            #     for k, v in kwargs.items():
            #         setattr(data, k, v)
            data.update(kwargs)
            super().__init__(data=data, status=http_status, headers=headers, exception=exception)

    视图类传递参数给序列化类

    # 1)在视图类中实例化序列化对象时,可以设置context内容
    # 2)在序列化类中的局部钩子、全局钩子、create、update方法中,都可以用self.context访问视图类传递过来的内容
    
    
    # 需求:
    # 1) 在视图类中,可以通过request得到登陆用户request.user
    # 2) 在序列化类中,要完成数据库数据的校验与入库操作,可能会需要知道当前的登陆用户,但序列化类无法访问request
    # 3) 在视图类中实例化序列化对象时,将request对象传递进去
    •  视图层
    class Book(APIView):
        def post(self, request, *args, **kwargs):
         # 这里将request传给序列化类,request包含了前端传来的所有信息 book_ser
    = serializers.BookModelSerializer(data=request_data,context={'request':request}) book_ser.is_valid(raise_exception=True) book_result = book_ser.save() return Response({ 'status': 0, 'msg': 'ok', 'results': serializers.BookModelSerializer(book_result).data })
    •  序列化层
    class BookModelSerializer(ModelSerializer):
        class Meta:
            model = models.Book
            fields = ('name', 'price')
        def validate_name(self, value):
            print(self.context.get('request').method)  # 此处拿的是请求方法
            return value
    补充:
      - data : 反序列化时,序列化类接收数据用 如:data=request_data
      - instance : 序列化时,序列化类接收model类对象用 如:instance=user_obj (可省略)
      - many : 序列化与反序列时,对象时多个时,需要指定 : many=True (本质是在遍历)
      - partial : 反序列化时,要进行局部改时,需要指定 : partial=True
      - context : 视图类向序列化类传递数据用, 如 : context={'request':request} 序列化类内部就可以拿到request,从而拿到request中的数据
  • 相关阅读:
    taglib
    ThinkPHP魔术方法
    给图片添加文字
    公益筹模板
    清空(数据库+文件夹)
    php——文件下载
    查询上一个tp语句
    安装wampserver 2.5的时候出现丢失MSVCR100.dll的解决办法。
    ThinkPHP3.2.3 安装教程
    java基础——File类的基本用法
  • 原文地址:https://www.cnblogs.com/waller/p/11700090.html
Copyright © 2011-2022 走看看