二次封装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中的数据

 

posted @ 2019-11-04 15:51  waller  阅读(287)  评论(0编辑  收藏  举报