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