class AbcViewset(ModelViewSet): permission_classes = (IsAuthenticated,) pagination_class = MaxSizePagination authentication_classes = (JSONWebTokenAuthentication, authentication.SessionAuthentication) def get_serializer_class(self): if self.action == "retrieve": return AbcSerializer elif self.action == "create": return AbcSerializer return AbcSerializer
class AbcSerializer(serializers.ModelSerializer): class Meta: model = AbcModel fields = "__all__"
在一个继承了`from rest_framework.viewsets.ModelViewSet`类的视图中,当使用list方法返回格式化数据的时候实际上是调用的`from rest_framework.mixins.ListModelMixin`类的list方法
当然retrieve方法返回数据调用的就是`from rest_framework.mixins.RetrieveModelMixin`类的retrieve,在这个方法中就会使用到`get_serializer`方法(action可以有增删改查和单独查的5个类别)
class RetrieveModelMixin: """ Retrieve a model instance. """ def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) return Response(serializer.data) class ListModelMixin: """ 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方法在from rest_framework.generics.GenericAPIView类中定义,在其中会调用到get_serializer_class方法在获取视图中定义的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
serializer类的继承关系是AbcSerializer -- rest_framework.serializers.ModelSerializer -- rest_framework.serializers.Serializer -- rest_framework.serializers.BaseSerializer
rest_framework.serializers.ListSerializer类也是继承的rest_framework.serializers.BaseSerializer类
在对serializer类做初始化的时候会执行rest_framework.serializers.BaseSerializer类的__new__和__init__(因为序列化类是继承的BaseSerializer类)
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().__init__(**kwargs) def __new__(cls, *args, **kwargs): # We override this method in order to automagically create # `ListSerializer` classes instead when `many=True` is set. if kwargs.pop('many', False): return cls.many_init(*args, **kwargs) return super().__new__(cls, *args, **kwargs) @classmethod def many_init(cls, *args, **kwargs): """ This method implements the creation of a `ListSerializer` parent class when `many=True` is used. You can customize it if you need to control which keyword arguments are passed to the parent, and which are passed to the child. Note that we're over-cautious in passing most arguments to both parent and child classes in order to try to cover the general case. If you're overriding this method you'll probably want something much simpler, eg: @classmethod def many_init(cls, *args, **kwargs): kwargs['child'] = cls() return CustomListSerializer(*args, **kwargs) """ allow_empty = kwargs.pop('allow_empty', None) child_serializer = cls(*args, **kwargs) list_kwargs = { 'child': child_serializer, } if allow_empty is not None: list_kwargs['allow_empty'] = allow_empty list_kwargs.update({ key: value for key, value in kwargs.items() if key in LIST_SERIALIZER_KWARGS }) meta = getattr(cls, 'Meta', None) list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer) return list_serializer_class(*args, **list_kwargs)
在这里对类的实例化的过程中会先调用__new__方法来看是需要导出数据集合还是单个数据(以many是不是为True来判断),如果为True将会执行many_init方法
在这里将child绑定到类实例本身,并返回ListSerializer类(将要初始化的类是ListSerializer)
class ListSerializer(BaseSerializer): child = None many = True def __init__(self, *args, **kwargs): self.child = kwargs.pop('child', copy.deepcopy(self.child)) self.allow_empty = kwargs.pop('allow_empty', True) assert self.child is not None, '`child` is a required argument.' assert not inspect.isclass(self.child), '`child` has not been instantiated.' super().__init__(*args, **kwargs) self.child.bind(field_name='', parent=self) def to_representation(self, data): """ List of object instances -> List of dicts of primitive datatypes. """ # Dealing with nested relationships, data can be a Manager, # so, first get a queryset from the Manager if needed iterable = data.all() if isinstance(data, models.Manager) else data return [ self.child.to_representation(item) for item in iterable ] @property def data(self): ret = super().data return ReturnList(ret, serializer=self)
当使用.data属性获取数据的时候就会开始真正的序列化过程了,这里的data方法中调用了父类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. ' '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
注意了在BaseSerializer类的data方法中,如果是many为True的情况下是调用的是ListSerializer类的to_representation方法,在这里将会把集合中的每一个数据做序列化操作,如果不是many为True那么就是调用的rest_framework.serializers.Serializer类的to_representation
方法(当然在ListSerializer类的to_representation方法中循环集合中的每个数据的时候也是调用rest_framework.serializers.Serializer类的to_representation方法)
class Serializer(BaseSerializer, metaclass=SerializerMetaclass): 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
在这里完成对数据的序列化,这里field就是我们在AbcSerializer中定义的字段了