我们都知道,在开发API接口时,最核心的事情有两点:
pythonh中序列化和反序列化的概念:
python对象
转换成json,xml等主流字符串格式的过程
总之,序列化器其实就是对数据库数据的读和写进行辅助简便处理的类。 所以序列化器和数据库模型类息息相关
已有一个数据库模型类UserInfo如下,我们想为此模型类提供序列化器,以此到达快速序列化和反序列化的目的。
(注意:serializer不是只能为数据库模型类的数据定义,也可以为⾮数据库模型类的数据定义。 serializer是独⽴于数据库之外的存在。)
from django.db import models
# Create your models here.
class UserInfo(models.Model):
#以下模型字段默认时不能为空 null=False
username = models.CharField(max_length=32, unique=True)
password = models.CharField(max_length=64)
group = models.ForeignKey("UserGroup", models.CASCADE)
roles = models.ManyToManyField("Role")
user_type = models.IntegerField(choices=((1, '普通用户'),(2, 'VIP'),(3, 'SVIP')))
class Meta:
db_table="tb_user"
verbose_name ="用户"
verbose_name_plural = verbose_name
class UserGroup(models.Model):
title = models.CharField(max_length=32)
class Role(models.Model):
title = models.CharField(max_length=32)
class UserToken(models.Model):
user = models.OneToOneField(to="UserInfo", on_delete=models.CASCADE)
token = models.CharField(max_length=64)
首先我们需要定义序列化类
我们一般通过继承Serializer或ModelSerializer定义某个序列化器类
注:基本都通过继承ModelSerializer来自定义序列化类,ModelSerializer是serializer的子类,在Serializer的基础上进⾏了代码简化
from rest_framework import serializers
# 声明序列化器,继承Serializer(所有的序列化器都要直接或者间接继承于 Serializer)
class StudentSerializer(serializers.Serializer):
# 我们必须在此定义需要进行序列化或者反序列化的字段
username = serializers.CharField()
name = serializers.CharField(source=“username”) # 这个name就是对应的数据库中的username字段
user_type = serializers.CharField(source="get_user_type_display")
gp = serializers.CharField(source="group.title") # 外键
rls = serializers.SerializerMethodField() # 自定义序列化字段
def get_rls(self, obj): # obj就是此模型实例,对应表中的一条记录,
ret = obj.rls + '加一个后缀把'
return ret
字段定义注意事项:
1.如果没有参数source参数,则定义的字段名称必须和数据库中字段名称相同
2.如果不想用数据库中的字段名称,可以加source参数,指明此字段来源于数据库中哪个字段
source="数据库字段名"
username = serializers.CharField(source=“name”) # 这个usemname就是对应的数据库中的name字段
3.很多字段 数据库是以key值存储的,比如user_type,但要想给用户展示的是value值。可以使用source=“get_数据库字段名_display”
source="get_数据库字段名_display"
user_type = user_type(source="get_user_type_display")
4.取外键关联,group是外键,可以直接使用 source=外键字段名.字段名 的方式 取到所关联表的某个字段
source=外键字段名.字段名
gp = serializers.CharField(source="group.title")
5.serializerMethodField
自定义序列化字段返回值 ,值由固定的命名规范方法 get_字段名 的返回值提供,此方法会把字段变成只读
SerializerMethodField必须在继承ModelSerializer后使用,并且SerializerMethodField不能添加validate_user_email这样的验证方法
在我们开发的时候,我么使用序列化器序列化返回的时候,返回的大多都是数据框中一个表中的字段,但是我们还想返回一些其他表(关联表)中的字段数据或者数据库中没有的字段怎么办,或者说返回别的数据,此时可以使用
这里的obj是Serializer的Model的模型实例,对应表中的一条记录
rls = serializers.SerializerMethodField() # 自定义序列化字段
def get_rls(self, obj): # obj就是此模型实例,对应表中的一条记录
ret = obj.rls + '加一个后缀把'
return ret
6.HiddleField隐藏字段
依靠输入,而需要设置默认的值,不需要用户自己post数据过来,也不会显式返回给用户,最常用的就是user
# 获取当前用户,并且隐藏了该字段,不会序列化返回给前端
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
原理:源码:提取request中的user,前端返回的token中会带上user信息
class CurrentUserDefault(object):
def set_context(self, serializer_field):
self.user = serializer_field.context['request'].user
def __call__(self):
return self.user
def __repr__(self):
return unicode_to_repr('%s()' % self.__class__.__name__
字段名 = serializers.字段类型(参数)
常用字段类型:
字段 | 字段构造方式 |
---|---|
BooleanField | BooleanField() |
NullBooleanField | NullBooleanField() |
CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
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) |
IntegerField | IntegerField(max_value=None, min_value=None) |
FloatField | FloatField(max_value=None, min_value=None) |
DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
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) |
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 | 最大值 |
前四个只支持CharField字段,后两个只支持IntegerField字段
参数名称 | 说明 |
---|---|
read_only | 表明该字段仅用于序列化输出,默认False |
write_only | 表明该字段仅用于反序列化输入,不用做序列化的输出,也就是只用于数据校验,默认False |
required | 表明该字段在反序列化时必须输入,默认True |
default | 反序列化时使用的默认值 |
allow_null | 表明该字段是否允许传入None,默认False |
validators | 该字段使用的验证器 |
error_messages | 包含错误编号与错误信息的字典 |
label | 用于HTML展示API页面时,显示的字段名称 |
help_text | 用于HTML展示API页面时,显示的字段帮助提示信息 |
read_only和write_only的进一步说明:
我们的字段默认都是既序列化又需反序列化的。
read_only=True,序列化时序列化出该字段数据,反序列化校验时不校验这个数据
write_only=True,序列化时不序列化这个字段数据,反序列校验时,需要客户端传递这个数据过来进⾏校验
在反序列化之前,我们需要对前端传过来的数据进行校验,因此我们需要事先定义好验证条件。
在定义序列化器时,每个字段的序列化类型和参数(比如max_length),对应模型字段的序列化类型和参数,本身就会产生一种验证行为。
除此以外, 我们还可以进行补充验证
error_messages 在定义字段时,参数error_messages可为某些参数指定错误提示信息
class UserInfoSerializer(serializers.ModelSerializer):
title = serializers.CharField(error_messages={
"blank": "请输入验证码",
"required": "请输入验证码",
"max_length": "验证码格式错误",
})
当然, 也可以在Meta元类中通过extra_kwargs直接为隐式字段传入额外参数error_messages
class Meta:
model = User
fields = ['id', 'username', 'password', 'mobile', 'passwordConfirm', 'smsCode']
# 给隐式字段 添加/修改属性
extra_kwargs = {
'username': {
'min_length': 5,
'max_length': 20,
'error_messages': {
'min_length': '仅允许5-20个字符的用户名',
'max_length': '仅允许5-20个字符的用户名',
}
},
'password': {
'write_only': True,
'min_length': 8,
'max_length': 20,
'error_messages': {
'min_length': '仅允许8-20个字符的密码',
'max_length': '仅允许8-20个字符的密码',
}
}
}
validators validators
参数可为字段补充自定义校验函数;列表格式,元素为验证函数
自定义验证函数(需要在序列化器类以外定义,通常会单独创建一个validators.py文件 从其引入函数)
自定义校验函数需要给定⼀个形参,⽤来接收待校验的数据,并且指定条件下要抛出serializers.ValidationError的异常,如果validators字段值的列表中有多个校验函数,校验过程中会全部进⾏校验,并以列表的形式返回⼀组异常校验信息
def is_contains_keyword(value):
if '项目' not in value:
raise serializers.ValidationError('项目名称中必须得包含“项目”关键字')
def is_not_contain_x(value):
if'X'in value.upper():
raise serializers.ValidationError("项⽬名字段name不能包含x的⼤⼩写字符")
name = serializers.CharField(max_length=20, validators=[is_contains_keyword, is_not_contain_x])
当然,也可直接调用drf自带的validators模块中的校验函数进行校验,就不用自己定义了。比如唯一校验UniqueValidator
唯一检验UniqueValidator需要指定查询集和错误提示信息,即传queryset和message两个参数
除了UniqueValidator的唯⼀校验,还有其它的唯⼀校验,根据不同的场景选择使⽤即可
extra_kwargs = {
'username': {
'min_length': 5,
'max_length': 20,
'error_messages': {
'min_length': '仅允许5-20个字符的用户名',
'max_length': '仅允许5-20个字符的用户名',
},
'validators': [UniqueValidator(queryset=User.objects.all(), message='此用户名已注册')],
},
}
validate_字段名 局部钩子:自定义校验方法
上面第2种采⽤的是在序列化器类外⾯创建的校验器函数,同样的也可以在序列化器类⾥定义校验器⽅法,也要在指定条件下要抛出serializers.ValidationError的异常,不同的有以下⼏点:
validate_字段名
方式命名def validate_mobile(self, mobile):
# 手机号是否注册
if User.objects.filter(mobile=mobile).count():
raise serializers.ValidationError("用户已经存在")
# 验证手机号是否合法
if not re.match(settings.REGEX_MOBILE,mobile):
raise serializers.ValidationError('手机号码非法')
# 验证验证码发送频率
one_minute_ago = datetime.now() - timedelta(hours=0,minutes=1,seconds =0)
if VerifyCode.objects.filter(add_time__gt=one_minute_ago,mobile=mobile).count():
raise serializers.ValidationError('请超过60s后再次发送')
return mobile
上面的方法我们都是单字段进行校验,如果是想要同时拿到多字段进行校验,就需要用到该方法
在序列化类中,方法名固定为validate,形参为attrs,attrs为待校验字段组成的字典
attrs返回一个QueryDict,字段名可以通过字典的方法进行取值,如:attrs[‘name’] 或者 attrs.get(‘name’)
必须返回形参attrs
validate也就是数据校验的全局钩子
def validate(self, attrs):
# 写校验逻辑
# 判断注册时填写的两次密码是否一致
if attrs.get('password') != attrs.get('passwordConfirm'):
raise serializers.ValidationError('两次密码不一致')
return attrs # 全局钩⼦validate最后都要return attrs
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WSCWOx7X-1659680817888)(https://img.conglinchu.top/i/image-python/212321312.png)]
如果验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。
如果是非字段错误,比如全局钩子validate没有验证通过,我们可以看到该异常校验信息字段的key为non_field_errors,
我们针对这个key可以进⾏修改,可以通过修改REST framework全局配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
REST_FRAMEWORK = {
'NON_FIELD_ERRORS_KEY': 'validate_errors'
}
这个键名就变成了validate_errors
数据校验顺序
对每个字段类型,参数进行校验
调用局部钩子validate_字段名 进行校验
全局钩子validate进行校验
使用字段选项中的validators执行外部函数的校验
我们都希望序列化器类紧密地映射到模型类上。ModelSerializer做到了这一点。所以我们一般都继承ModelSerializer来定义序列化器。
ModelSerializer类继承于Serializer类,在Serializer的基础上进行了简化,它在Serializer的基础上又提供了以下几点:
基于模型类⾃动⽣成⼀系列字段
基于模型类⾃动为Serializer⽣成validators,⽐如unique_together
包含默认的create()和update()的实现
from rest_framework import serializers
from .models import UserInfo
class StudentSerializer(serializers.ModelSerializer):
# 在此你仍然可以显示的声明字段,就像 Serializer 类一样。
# 你可以声明和数据库字段同名的字段来覆盖默认字段
class Meta:
model = UserInfo # 指明该序列化器处理的数据字段从模型类UserInfo参考生成
fileds = '__all__'
在自定义序列化器类中定义元类Meta,关于元类Meta:
model 指明模型类对象,来指明此序列化类是为哪张表提供序列化服务。
fields 指明参与该序列化器的字段
fileds = ‘__all__’ # 指明 数据库表所有字段 + 自定义的所有字段 进行序列化或反序列化
(具体参与序列化还是反序列化,还得看字段的write_only 和 read_only 属性)
fields = ['‘username’, ‘user_type’] # 指明就列表内的这些字段参加序列化或反序列化 我们一般使用这种
exclude = [‘id’, ‘password’] # 排除掉具体某些字段
fields和exclude不能同时存在,也不能同时不存在
read_only_fields 指定多个字段为只读
希望将多个字段指定为只读,而不是显式地为每个字段添加read_only=True属性
read_only_fields = [“id”]
只读字段只做序列化,不做反序列化
模型中已经设置 editable=False
的字段 和 默认就被设置为只读的 AutoField
字段都不需要添加到 read_only_fields
选项中。
extra_kwargs 给隐式字段添加额外参数
使用 extra_kwargs
选项在字段上指定任意附加关键字参数
一般给默认字段添加,这样就不需要在序列化器中显式得再声明一遍该字段。
比如模型类中的password最大长度是150,想修改到20,直接可以通过extra_kwargs为password字段添加参数
extra_kwargs = {
'username': {
'min_length': 5,
'max_length': 20,
'error_messages': {
'min_length': '仅允许5-20个字符的用户名',
'max_length': '仅允许5-20个字符的用户名',
}
},
'password': {
'min_length': 8,
'max_length': 20,
'error_messages': {
'min_length': '仅允许8-20个字符的密码',
'max_length': '仅允许8-20个字符的密码',
},
'user_type': {
'source': ’get_user_type_display‘
}
}
}
如果字段已在序列化程序类中显式声明,则extra_kwargs中此字段将被忽略。
注意只是为此字段添加参数,不会改变字段的类型,如果想改变字段的类型,请显示的定义字段来达到覆盖
当然,如果你你不嫌麻烦,可以通过显示定义的方式重新覆盖。
depth 外键关系序列化
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
depth = 1 # 建议1或2或3
在开发REST API的视图中,虽然每个视图具体操作的数据不同,但增、删、改、查的实现流程基本套路化,所以这部分代码也是可以复用简化编写的:
增:校验请求数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
删:判断要删除的数据是否存在 -> 执行数据库删除
改:判断要修改的数据是否存在 -> 校验请求的数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
查:查询数据库得到数据库模型对象或querySet -> 将数据序列化并返回
Serializer的构造方法为:
ser = StudentSerializer(instance=None, data=empty, **kwarg)
说明:
用于序列化时,必须将模型类对象或querySet查询集 传入instance参数,且不传入data
用于反序列化时,必须将被反序列化的字典传入data参数
除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如:
serializer = StudentSerializer(account, context={'request': request})
通过context参数附加的数据,可以通过Serializer实例的context属性获取,如在create方法中:self.context[‘request’]。
使用场景:
在视图类中,可以通过request得到登陆用户request.user,在序列化类中,要完成数据库数据的校验与入库操作,可能会需要知道当前的登录用户,但序列化类无法访问request对象,在视图类中实例化序列化对象时,可以通过context参数将request对象传递进去
book_ser = BookSerializer(context = {'request': request}, instance = objs, data = new_request_data, partial = True, many = True)
在create,update,或validate方法中就可以通过self.context[‘request’] 拿到request
2. DRF在序列化图片url字段的时候 会检查上下文有没有request,如果有,就给图片加上域名,也就是绝对路径,没有这个上下文,就会是相对路径,想要绝对路径,就要加上context = {'request': request}
反序列化即将如json等字符串转换成python对象的过程
我们可以通过视图的request拿到字典格式的前端数据,序列化器可以对其进行校验,并保存到数据库中。
所以我们的关注点是:
创建序列化对象
调用数据验证
对数据进行持久化,包括:新增create 或者 更新update
默认所有的required字段都必须参与反序列化,除非此字段read_only为true
当然如果此字典中还包括了一些无关的字段,序列化器会忽略掉,没有经过后期校验的字段不会出现在validated_data中
s = CreateUserSerializer(data=all_list)
如果data传递的字典中没有囊括所有需要反序列化的字段,需要增加参数 partial=True(表示部分更新)
如果未传instance,则表示部分添加(前提是,未传字段对应的数据库字段允许未空!!)
如果传了instance,则表示对此模型实例进行部分更新
# 当数据库允许为空,但是序列化器要求必须字段填写的时候,可以使用以下方式避开
serializer = StudentSerializer(data=part_lsit, partial=True)
更新学生的部分字段信息,
updated_server = ServerManager.objects.get(id=request.data['id'])
s = ServerManagerSerializer(instance=updated_server, data=updated_data, partial=True)
注意:如果我们漏传需要参加反序列化字段,并且添加了partial=True,那么只会校验传⼊给序列化器的这些数据,但我们的局部钩子中,很可能会取validated_data中某些字段,取不到也有可能被我们抛异常。
所以要么是真正的部分更新成功,要么会报错,不太会出现漏传却部分更新成功的情况,基本都是我们刻意进行的部分更新。
传递data后,可以通过序列化器实例的initial_data属性 获取将要进行验证的数据
进行数据持久化之前,必须调用序列化器实例的**is_valid()**方法进行数据校验
s = CreateUserSerializer(data=all_list)
s.is_valid() # 成功返回True, 失败返回False
在调用valid()方法以后,序列化器实例的 validated_data , errors,都会变成可获得的
s.validated_data 验证成功后,可以通过序列化器实例的validated_data属性 获取通过验证的数据
s.errors 验证失败,可以通过s.errors获取错误信息
is_valid(raise_exception=True)
is_valid方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过raise_exception=True参数开启,
一旦检出错误,程序就会终止,自动return。所以我们一般不使用这个参数,直接判断is_valid是否为false,拿s.errors返回即可
在数据校验成功后,调用序列化器的**save()**方法进行数据的保存或更新
其实你不调用save也行,直接在视图中写逻辑
调用序列化器的save()方法后,如果未传instance,save方法则会调序列化器的create()方法
调用序列化器的save()方法后,如果传了instance,save方法则会调序列化器的update()方法
所以save()方法本质是调用序列化器的create或update方法,save()返回值自然也是create()或者update()方法的返回值
s = CreateUserSerializer(data=created_list)
if s.is_valid():
s.save()
在对序列化器进行save()保存时,可以额外传递数据,这些数据会直接放到validated_data中,当然create和update就可以获取到
s.save(owner=request.user) # owner=request.user 会新增在validated_data字典中
在调用save()方法以后,序列化器实例的 data 会变成可获得的
s.data即为反序列化传入数据 成攻创建或更新的数据库模型实例 序列化以后的数据。
实际上,save方法也可重写,只不过很少需要
我们可能不需要创建新的实例,而是使用validated_data中的数据发送电子邮件或做其他的事情。
这些情况下,可以选择直接重写 .save()
,因为这样更具有可读性和意义。
请注意,在上面的情况下,我们现在必须直接访问序列化器 validated_data
属性。
def save(self):
email = self.validated_data['email']
message = self.validated_data['message']
return send_email(from=email, message=message)
create方法和update方法
如果序列化类继承Serializer,必须重写create方法和update方法,才能实现反序列化数据的新增和更新
如果序列化器类继承ModelSerializer,ModelSerializer自带了create方法和update方法
ModelSerializer中create方法是对此模型类执行create操作,传参为validated_data
ModelSerializer中update方法是对此模型类执行update操作,传参为instance, validated_data
create方法和update方法 必须返回一个实例
ModelSerializer默认create和update方法基本相当于:
def create(self, validated_data):
return ExampleModel.objects.create(**validated_data)
def update(self, instance, validated_data):
for attr, value in validated_data.items():
setattr(instance, attr, value) # setattr(x, 'y', v) is equivalent to ``x.y = v''
instance.save()
return instance
# 注:ModelSerializer中的update是使用instance.key = value的方式进行修改的。
# 如果此模型类没有这个字段,就不会实际进行持久化,也不会报错,所以ModelSerializer的update方法实际上可以不用修改。
但一般我们总是重写,主要有以下情况:
需要删除 validated_data 中不能保存在数据库中的字段
进行反序列化校验的参数通常都不一定最后要保存到数据库模型中,数据库也可能没有此字段,比如手机验证码,没有必要保存到数据库中,数据库可能也压根没有此字段。且主要因为数据库模型的创建方法ExampleModel.objects.create无法接收不是数据库字段的参数,会报错。所以我们一般要把validated_data中不能保存在数据库中的字段删除。
**注:**ModelSerializer中的update()方法是使用instance.key = value的方式进行修改的。如果此模型类没有这个字段,就不会实际进行持久化,也不会报错,所以update方法不用担心validated_data有多余字段的问题,这个情况下就不用重写ModelSerializer中的update()方法了。
调用外部函数
比如用户密码,需要对明文密码进行哈希处理后再存入数据库,就需要重写
def create(self, validated_data):
# 删除 validated_data 中不能保存在数据库中的字段
del validated_data['passwordConfirm']
del validated_data['smsCode']
# 先调用ModelSerializer的create方法保存数据,但password现在是明文的
user = super().create(validated_data)
#相当于ExampleModel.objects.create(**validated_data)
# 调用set_password方法重新哈希设置密码 set_password方法是AbstractBaseUser类
user.set_password(validated_data['password'])
user.save()
return user
将数据库模型类转换成字典,并通过视图的Response返回json给前端。
所以我们的关注点是:
创建序列化对象,
传入待序列化的模型实例 或 QuerySet查询集
分页
务必传入instance,且不传入data,instance为 模型实例 或 querySet查询集
若要序列化的 是查询集querySet 并不是单个对象实例,实例化时,必须传入many=True
queryset = Book.objects.all()
s = BookSerializer(instance=queryset, many=True)
实际上,通过源码可知,对于单个对象实例,采用的是Serializer类进行处理, 若对象是QuerySet,采用ListSerializer处理
通过data属性可以获取序列化后的数据
queryset = Book.objects.all()
s = BookSerializer(instance=queryset, many=True)
s.data # 序列化以后的数据
通过视图的Response将序列化以后的数据,即:data属性 返回成json字符串
class BookListView(APIView):
def get(self, request, *args, **kwargs):
queryset = Book.objects.all()
s = BookSerializer(instance=queryset, many=True)
return Response(s.data, status=status.HTTP_200_OK)
4.一般都会搭配drf的分页,这个记录在分页器中。
继承ModelSerializer
明确哪些字段需要序列化,哪些字段需要反序列化,哪些字段只需要序列化,哪些字段只需要反序列化
fileds = '__all__'
代表参与序列化和反序列化的字段为:所有的数据库字段 + 自定义的新字段
fileds = ['id', 'username']
代表参与序列化和反序列化的字段就是列表中的这些
序列化器会根据字段的write_only和read_only属性再去判断哪些序列化,哪些反序列化
我们的字段默认都是既序列化又需反序列化的。
read_only=True,仅对此字段进行序列化,反序列化校验时不校验这个数据
write_only=True,此字段不参与序列化,反序列时,需要客户端传递这个数据过来进⾏校验
设置校验规则: 参数校验 ,validtors外部校验函数 , 局部钩子valid_字段名 ,全局钩子validate
重写create或undate方法,如果某些字段不入库,可以将其从validated_data删除。
序列化就是从数据库模型中取数据,比较好操作,主要需要搭配分页。