序列化组件

序列化组件

序列化介绍

作用:

  1. 序列化,序列化器(类)会把模型对象(Book对象,Queryset对象)转换成字典,经过response以后变成json字符串
  2. 反序列化,把客户端发送过来的数据,经过request以后变成字典(request.data),序列化器(类)可以把字典转成模型
  3. 反序列化,完成数据校验功能

本质:

就是写一个类,继承一个基类
可以完成序列化,反序列化和数据校验

序列化Serializer类的使用

1 视图类

### 序列化器的使用
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Books
from rest_framework.request import Request
from .serizlizer import BookSerializer
class BookAPIView(APIView):
    #查询所有接口
    def get(self, request, *args, **kwargs):
        book_list=Books.objects.all()
        # 序列化过程,把queryset转成字典
        # 第一个参数是要序列化的对象,如果序列化多条数据,一定要加上many=True
        ser=BookSerializer(instance=book_list,many=True)
        print(ser.data)
        return Response(ser.data)
    def post(self, request, *args, **kwargs):
        ser=BookSerializer(data=request.data) #新增,不用传instance
        if ser.is_valid():
            ser.save()
            return Response(ser.data)

class BookDetailAPIView(APIView):
    # 查询单个
    def get(self, request, pk):
        book = Books.objects.filter(pk=pk).first()
        # 序列化过程,把Book转成字典
        # 第一个参数是要序列化的对象,如果序列化多条数据
        ser = BookSerializer(instance=book)
        print(ser.data)
        return Response(ser.data)
    def delete(self,request,pk):
        Books.objects.filter(pk=pk).delete()
        return Response()
    def put(self,request,pk):
        book=Books.objects.filter(pk=pk).first()
        # 反序列化,修改
        # instance 传要修改的对象
        ser=BookSerializer(instance=book,data=request.data)  #修改
        # 校验数据
        if ser.is_valid():
            ser.save() # 报错
            return Response(ser.data)

2 序列化类

from rest_framework import serializers
from .models import Books
class BookSerializer(serializers.Serializer):
    #写字段(要序列化,反序列化的字段)
    name=serializers.CharField()
    price=serializers.IntegerField()
    publish=serializers.CharField()

    # 如果要更新,一定要重写update方法
    def update(self, instance, validated_data):
        # 修改
        instance.name=validated_data.get('name')
        instance.price=validated_data.get('price')
        instance.publish=validated_data.get('publish')
        # 保存
        instance.save()
        # 返回
        return instance
    # 如果要新增,一定要重写create方法
    def create(self, validated_data):
        # 保存
        book=Books.objects.create(**validated_data)
        # 一定记得return
        return book

3 路由

urlpatterns = [
    # drf继承APIView的路由
    path('books/', views.BookAPIView.as_view()),
    path('books/<int:pk>', views.BookDetailAPIView.as_view()),
]

4 模型

class Books(models.Model):
    name=models.CharField(max_length=32)
    price=models.IntegerField()
    publish=models.CharField(max_length=32)

serializer高级使用

1 source参数
	- 指定对应模型的字段或方法(表模型中写的方法,方法返回的结果就是这个字段的值)
	- book_name=serializers.CharField(source="name")

2 给字段加自己的校验规则
	- name=serializers.CharField(max_length=8,min_length=3)

3 SerializerMethodField
	- 在序列化中写方法,使其返回结果映射个对应的字段
	publish=serializers.SerializerMethodField()
	def get_publish(self,obj):
		return {'name':obj.publish.name,'addr':obj.publish.addr}

4 局部钩子
	def validate_name(self,name):
        if name.startswith('sb'):
            raise ValidationError('不能以sb开头')
        else:
            return name

5 全局钩子
	def validate(self, attrs):
		print(attrs.get('name'))
         print(attrs.get('addr'))
         return attrs
serializer在映射表字段时没有指定的表,而ModelSerializer的类与表有一一对应,所以在用serializer类写修改表数据和添加表数据时要重写create,update方法

序列化类如果传了instance,调用save方法触发update,否则触发create
       if self.instance is not None:
            self.instance = self.update(self.instance, validated_data)
        else:
            self.instance = self.create(validated_data)
class PublishSerializer(serializers.Serializer):
    name=serializers.CharField(max_length=8,min_length=3)
    addr=serializers.CharField(max_length=8,min_length=3)
    def validate_name(self,name):
        if name.startswith('sb'):
            raise ValidationError('不能以sb开头')
        else:
            return name
    def validate(self, attrs):
        name=attrs.get('name')
        print(name)
        addr=attrs.get('addr')
        print(addr)
        return attrs
    def create(self, validated_data):
        # 保存
        publish=Publish.objects.create(**validated_data)
        # 一定记得return
        return publish

ModelSerializer使用

1 继承ModelSerializer
	- class PublishModelSerializer(serializers.ModelSerializer):
2 字段通过表模型映射
	class Meta:
        model = Pubilsh  # 指定对应的表(model不能改成其他名字)
        fields = '__all__'  # 序列化所有字段
        fields = ['id', 'name', 'addr']  # 序列化指定字段,可以加上方法
        exclude = ['id']  # 将某些字段排除,不能与dields一起使用
        # depth = 1  # 指定映射深度,外键关联的深度,1表示一层外键表,一般不用

3 反序列化时,字段自己的校验规则映射了表模型的
4 可以重写字段来改变规则
5 可以扩写字段(表模型中没有的字段)

6 局部钩子和全局钩子和Serializer一样使用

7 wirte_only和read_only参数
    # 该字段反序列化时候使用,  序列化时候不用
    # name=serializers.CharField(write_only=True)

    # 该字段序列化的时候使用,反序列化不用 (字段没写可为空会存不进去)
    # name=serializers.CharField(read_only=True)
8 extra_kwargs
	class Meta:
		model = Pubilsh
		fields = ['id', 'name', 'addr']
		extra_kwargs={'name':{'write_only':True,'max_length':8}}
	# 额外给字段传递参数,类似于重写字段:
	# name = serializers.CharField(write_only=True,'max_length':8)

字段和参数补充

常用字段

字段 字段构造方式
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
IntegerField IntegerField(max_value=None, min_value=None)
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
BooleanField BooleanField()
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
NullBooleanField NullBooleanField()
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose'"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex'"5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
IPAddressField IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
FloatField FloatField(max_value=None, min_value=None)
DurationField DurationField()
ChoiceField ChoiceField(choices) choices与Django的用法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

指定参数

参数名称 作用
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空,传值时可不穿
trim_whitespace 是否截断空白字符
max_value 最小值
min_value 最大值

通用参数

参数名称 说明
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息

钩子函数的源码分析

# 入口是 ser.is_valid(),是BaseSerializer的方法
# 最核心的代码
	self._validated_data = self.run_validation(self.initial_data) # 切记不要按住ctrl点
    
# run_validation 调用的是Serializer类的方法
	def run_validation(self, data=empty):
        value = self.to_internal_value(data) # 局部钩子的代码
        try:
            self.run_validators(value)
            value = self.validate(value)  # 全局钩子的执行
            assert value is not None, '.validate() should return the validated data'
            except (ValidationError, DjangoValidationError) as exc:
                raise ValidationError(detail=as_serializer_error(exc))
        return value
    
    
# 局部钩子核心代码
	for field in fields:
        validate_method = getattr(self, 'validate_' + field.field_name, None) #反射字段的局部钩子方法
        try:
            if validate_method is not None:
                validated_value = validate_method(validated_value) #执行局部钩子方法
        except ValidationError as exc:
            errors[field.field_name] = exc.detail
        except DjangoValidationError as exc:
            errors[field.field_name] = get_error_detail(exc)

序列化组件部分源码分析

# 1 对象的实例化过程,__new__在__init__之前执行,new是造对象,init是初始化对象
# 2 序列化类在实例化的时候,先调用的是BaseSerializer中的__new__
def __new__(cls, *args, **kwargs):
	if kwargs.pop('many', False):
        return cls.many_init(*args, **kwargs)  ##实例化出ListSerializer的对象
    return super().__new__(cls, *args, **kwargs) # 实例化出自己的对象
    
def many_init(cls, *args, **kwargs):
    return list_serializer_class(*args, **list_kwargs)

# 3 ListSerializer 和BookSerializer有什么联系
	- ListSerializer类似于列表一样包括了多个BaseSerializer,但其本身不是列表
	-[ser1,ser2,ser3]

posted @ 2021-07-23 20:58  zheng-sn  阅读(65)  评论(0)    收藏  举报