DRF源码-serializers
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: 如果传递data=这个参数 .is_valid() - Available.可用 .initial_data - Available.可用 .validated_data - Only available after calling `is_valid()`调用is_valid之后可用 .errors - Only available after calling `is_valid()` .data - Only available after calling `is_valid()` If a `data=` argument is not passed then: 一般来水不会传递data这个参数 .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): #初始化,传入instance参数(一个model class的实例) self.instance = instance #instance给到self if data is not empty: self.initial_data = data self.partial = kwargs.pop('partial', False) #将额外的字典参数中,partial,context给到self,如果没有,给出默认值 self._context = kwargs.pop('context', {}) kwargs.pop('many', None) #将many这个key删除 super().__init__(**kwargs) #继承父类的其余属性
# 对self.data属性函数化,为了加判断 # 将instance转化为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
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
# 继承父类的data属性,然后调用ReturnDict函数返回 @property def data(self): ret = super().data return ReturnDict(ret, serializer=self)
app目录
serializer.py
# 创建serializers.Serializer的子类 # 几个field是Fields.py里Field的几个子类 class ColorsSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) colors = serializers.CharField(max_length=10) def create(self, validated_data): return Colors.objects.create(**validated_data) def update(self, instance, validated_data): instance.colors = validated_data.get('colors', instance.colors) instance.save() return instance
views.py
def test(request): color = Colors(id=2,colors='red') #color为一个xxx.models.Colors的instance print(color) #一个instance,由该model类的__str__(self)的返回值决定 serializer = ColorsSerializer(instance=color) #将这个instance传入序列化类,返回一个序列化实例 print(serializer.data) # <class 'rest_framework.utils.serializer_helpers.ReturnDict'> print(type(serializer.data)) # {'id': 2, 'colors': 'red'} return HttpResponse('done')
class ModelSerializer(Serializer):
""" A `ModelSerializer` is just a regular `Serializer`, except that: * A set of default fields are automatically populated. * A set of default validators are automatically populated. * Default `.create()` and `.update()` implementations are provided. *将自动填充一组默认字段。 *将自动填充一组默认验证器。 *提供了默认的`.create()`和`.update()`实现。elds The process of automatically determining a set of serializer fields based on the model fields is reasonably complex, but you almost certainly don't need to dig into the implementation. If the `ModelSerializer` class *doesn't* generate the set of fields that you need you should either declare the extra/differing fields explicitly on the serializer class, or simply use a `Serializer` class. 如果“modelserializer”class没有生成所需字段,我应该在序列化类明确申明额外字段 或者直接使用Serializer类 """
# Default `create` and `update` behavior... def create(self, validated_data): """ We have a bit of extra checking around this in order to provide descriptive messages when something goes wrong, but this method is essentially just: 我们在这里有一些额外的检查,为了当发生错误时可以提供一些可描述的信息。 但这个方法,本质上就是: return ExampleModel.objects.create(**validated_data) If there are many to many fields present on the instance then they cannot be set until the model is instantiated, in which case the implementation is like so: 如果实例中有多对对字段,需要以下实现:先把字段从validated_data pop出来, example_relationship = validated_data.pop('example_relationship') instance = ExampleModel.objects.create(**validated_data) instance.example_relationship = example_relationship return instance The default implementation also does not handle nested relationships. If you want to support writable nested relationships you'll need to write an explicit `.create()` method. """ raise_errors_on_nested_writes('create', self, validated_data) # 在Meta嵌套类中的model属性 ModelClass = self.Meta.model # Remove many-to-many relationships from validated_data. # They are not valid arguments to the default `.create()` method, # as they require that the instance has already been saved. # 把model类的字段信息给到info # 处理多对多字段 info = model_meta.get_field_info(ModelClass) many_to_many = {} for field_name, relation_info in info.relations.items(): if relation_info.to_many and (field_name in validated_data): many_to_many[field_name] = validated_data.pop(field_name) # 表插入,返回到instance try: instance = ModelClass._default_manager.create(**validated_data) except TypeError: tb = traceback.format_exc() msg = ( 'Got a `TypeError` when calling `%s.%s.create()`. ' 'This may be because you have a writable field on the ' 'serializer class that is not a valid argument to ' '`%s.%s.create()`. You may need to make the field ' 'read-only, or override the %s.create() method to handle ' 'this correctly.\nOriginal exception was:\n %s' % ( ModelClass.__name__, ModelClass._default_manager.name, ModelClass.__name__, ModelClass._default_manager.name, self.__class__.__name__, tb ) ) raise TypeError(msg) # Save many-to-many relationships after the instance is created. if many_to_many: for field_name, value in many_to_many.items(): field = getattr(instance, field_name) field.set(value) return instance
# 在instance上设定每个属性,然后save def update(self, instance, validated_data): raise_errors_on_nested_writes('update', self, validated_data) info = model_meta.get_field_info(instance) # Simply set each attribute on the instance, and then save it. # Note that unlike `.create()` we don't need to treat many-to-many # relationships as being a special case. During updates we already # have an instance pk for the relationships to be associated with. m2m_fields = [] for attr, value in validated_data.items(): if attr in info.relations and info.relations[attr].to_many: m2m_fields.append((attr, value)) else: setattr(instance, attr, value) instance.save() # Note that many-to-many fields are set after updating instance. # Setting m2m fields triggers signals which could potentialy change # updated instance and we do not want it to collide with .update() for attr, value in m2m_fields: field = getattr(instance, attr) field.set(value) return instance # Determine the fields to apply...
app目录
serializers.py
class ColorsSerializer(serializers.ModelSerializer): class Meta: model = Colors fields = ('url', 'id', 'colors')
views.py
def test(request): color = Colors(id=2,colors='red') print(color) serializer = ColorsSerializer(instance=color,context={'request': request}) print(serializer.data) print(type(serializer.data)) return HttpResponse('done')
几种多表操作的field应用
读取外键的某个字段
# Clothes的color是外键,默认情况下,color字段会对应母表的主键,id。 # 使用SlugRelatedField可以指向外键,slug_field表示获取哪个字段返回给color # 这里color这个属性就被重写了 class ClothesSerializer(serializers.ModelSerializer): color = serializers.SlugRelatedField(queryset=Colors.objects.all(), slug_field='colors_cn') class Meta: model = Clothes fields = ('url', 'id', 'color', 'desc')