对基于视图的 几大视图类 跟 rest_framework 的 序列化过程
django 的 视图类 分为两大派系。
第一种是 django 自带的templateview 。
templateview 源码
class TemplateView(TemplateResponseMixin, ContextMixin, View):
"""
Render a template. Pass keyword arguments from the URLconf to the context.
"""
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
templateview 自己实现了 get 方法 而 它的 get_context_data 方法 跟 render_to_response 方法都是继承自父类。render_to_response 是继承TemplateResponseMixin 类,get_context_data 是继承ContextMixin 。源码就不贴出来了,很简单。
第二种 是 是 rest_framework_bulk 的ViewSet 类。BulkModelViewSet 所有的方法 create , list, 等等方法继承自父类,举个列子 而 list 方法中 用到的 get_queryset filter_queryset get_serializer 也是 继承自父类 ,需要时进行重写。
class BulkModelViewSet(bulk_mixins.BulkCreateModelMixin,
bulk_mixins.BulkUpdateModelMixin,
bulk_mixins.BulkDestroyModelMixin,
ModelViewSet):
下面分析 rest_framework 的 序列化 过程
如果 django rest_framework 需要对数据进行序列化操作,这是 restifulj 接口的 一部分,在 viewset 类 调用 list ,crate,等方法的之后 会 对 model orm 查询产生的 结果集 ,ListModelMixin 为例以 下面看 源代码。
class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
这个会调用 get_serializer 方法 对 对象 进行序列化操作,按照 python 继承规则 ,查找 get_serializer 方法, 源码 如下,
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def get_serializer_class(self):
"""
Return the class to use for the serializer.
Defaults to using `self.serializer_class`.
You may want to override this if you need to provide different
serializations depending on the incoming request.
(Eg. admins get full serialization, others get basic serialization)
"""
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
)
return self.serializer_class
对 viewset 类 有没有 serializer_class 做了一个 判断。没有 serializer_class 断言报错。如有有 就 把 data 传进serializer_class 的__init__方法。返回list 方法 返回 response 对象的 时候,这个数据集 作为了 serializer_class 的属性 一起返回去。serializer.data 见源码。
class BaseSerializer(Field):
"""
The BaseSerializer class provides a minimal class which may be used
for writing custom serializer implementations.
Note that we strongly restrict the ordering of operations/properties
that may be used on the serializer in order to enforce correct usage.
In particular, if a `data=` argument is passed then:
.is_valid() - Available.
.initial_data - Available.
.validated_data - Only available after calling `is_valid()`
.errors - Only available after calling `is_valid()`
.data - Only available after calling `is_valid()`
If a `data=` argument is not passed then:
.is_valid() - Not available.
.initial_data - Not available.
.validated_data - Not available.
.errors - Not available.
.data - Available.
"""
def __init__(self, instance=None, data=empty, **kwargs):
self.instance = instance
if data is not empty:
self.initial_data = data
self.partial = kwargs.pop('partial', False)
self._context = kwargs.pop('context', {})
kwargs.pop('many', None)
super(BaseSerializer, self).__init__(**kwargs)
当 结果集 传到 serializer_class 形参 instance 接收了这个参数,然后 BaseSerializer 的 data 属性是什么,贴出源码
@property
def data(self):
if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):
msg = (
'When a serializer is passed a `data` keyword argument you '
'must call `.is_valid()` before attempting to access the '
'serialized `.data` representation.\n'
'You should either call `.is_valid()` first, '
'or access `.initial_data` instead.'
)
raise AssertionError(msg)
if not hasattr(self, '_data'):
if self.instance is not None and not getattr(self, '_errors', None):
self._data = self.to_representation(self.instance)
elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
return self._data
这个data 属性 , 看源码 会 调用 to_representation 方法 对 _instaance 进行除了 ,这个 _instance 属性 保存了 结果集,下面看
to_representation 是什么样的?按照 继承 顺序 查找 to_representations 源码如下
def to_representation(self, instance):
"""
Object instance -> Dict of primitive datatypes.
"""
ret = OrderedDict()
fields = self._readable_fields
for field in fields:
try:
attribute = field.get_attribute(instance)
except SkipField:
continue
# We skip `to_representation` for `None` values so that fields do
# not have to explicitly deal with that case.
#
# For related fields with `use_pk_only_optimization` we need to
# resolve the pk value.
check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
if check_for_none is None:
ret[field.field_name] = None
else:
ret[field.field_name] = field.to_representation(attribute)
return ret
就是 Serializer 根据自己的 filed 取出 queryset 中的相关字段 ,放进一个有序列表里面,作为Serializer 的data 属性。所谓序列化过程就是这个样子,list 方法 >> queset>> 序列化>> 返回前端。