DRF的序列化器Serializer
一 序列化器的作用
- 1. 序列化,序列化器会把模型对象转换成字典,经过视图中response对象以后变成json字符串
- 2. 反序列化,视图中request会把客户端发送过来的数据转换成字典,序列化器可以把字典转成模型
- 3. 反序列化,把客户端发送过来的数据进行校验,并存储入库
二 定义序列化器
Django REST framework中的Serializer使用类来定义,必须直接或间接继承于rest_framework.serializers.Serializer。
我们已有了一个数据库模型类stuapi/Student,我们想为这个Student模型类提供一个序列化器类,可以定义如下,sers/serializers.py,代码:
from rest_framework import serializers
"""
rest_framework.serializers 是drf提供给开发者调用的序列化器模块
里面声明了所有的可用序列化器的基类,常用的有:
Serializer 序列化器基类,drf中所有的序列化器类都必须继承于 Serializer
ModelSerializer 模型序列化器基类,是序列化器基类Serializer的子类,在工作中,除了Serializer基类以外,最常用的序列化器类基类
""" class StudentSerializer(serializers.Serializer):
"""学生信息序列化器"""
# 1. 转换的字段声明
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
description = serializers.CharField() # 2. 如果当前序列化器继承的是ModelSerializer,则需要声明调用的模型信息
# class Meta:
# model = 模型
# fields = "__all__"
# fields = ["字段1","字段2",....] # 3. 验证代码的对象方法
# def validate(self, attrs): # 方法名validate是固定的,attrs就是客户端发送的数据,字典格式
# pass
# return attrs # def validate_<字段名>(self, data): # 方法名的格式必须以 validate_<字段名> 为名称,否则序列化器不识别!
# pass
# return data # 4. 模型操作的扩展方法
# def create(self, validated_data): # 添加数据操作,添加数据以后,就自动实现了从字典变成模型对象的过程
# pass
#
# def update(self, instance, validated_data): # 更新数据操作,更新数据以后,就自动实现了从字典变成模型对象的过程
# pass
sers/serializers.py
️ serializer不是只能为数据库模型类转换数据格式,也可以为非数据库模型类的转换数据格式。serializer是独立于数据库之外的存在。
serailziers中的字段声明时提供给客户端的,所以常用字段类型:
序列化器 字段 | 模型 字段 | 序列化器字段选项 |
---|---|---|
BooleanField | BooleanField | BooleanField() |
CharField | CharField TextField等 | CharField( max_length=最大长度, min_length=最小长度, allow_blank=False, 表示是否允许客户端提交空字符串,False表示不允许 trim_whitespace=True,表示是否移除字符串两边的空白字符,True表示移除 ) |
EmailField | EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
RegexField | CharField | RegexField(regex=正则表达式, max_length=None, min_length=None, allow_blank=False) |
SlugField | SlugField | SlugField(max_length=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9*-]+ |
URLField | URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
UUIDField | UUIDField | UUIDField(format='hex_verbose') format: 设置UUID格式,一般默认使用hex_verbose 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 'int' - 如: "123456789012312313134124512351145145114" 'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" |
IPAddressField | IPAddressField | IPAddressField(protocol='both', unpack_ipv4=False, **options) |
IntegerField | SmallIntegerFiled IntegerField BigIntegerField | IntegerField(max_value=最大值, min_value=最小值) |
FloatField | FloatField | FloatField(max_value=None, min_value=None) |
DecimalField | DecimalField | DecimalField( max_digits=数值的数字总个数, decimal_places=小数位个数, coerce_to_string=None, max_value=None, min_value=None) |
DateTimeField | DateTimeField | DateTimeField( format=api_settings.DATETIME_FORMAT, 表示日期格式 input_formats=None) |
DateField | DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
TimeField | TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
DurationField | DurationField | DurationField() |
ChoiceField | 对应整型或字符串中的choices=属性选项 | ChoiceField(choices=元祖选项) choices与Django的用法相同 |
MultipleChoiceField | 对应整型或字符串中的choices=属性选项 | MultipleChoiceField(choices=元祖选项) choices与Django的用法相同 |
FileField | FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ImageField | ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ListField | python里面的List | ListField(child=模型列表, min_length=None, max_length=None) |
DictField | python里面的Dict | DictField(child=模型对象) |
字段的选项参数:
参数名称 |
作用 |
---|---|
max_length | 最大长度 |
min_lenght | 最小长度 |
allow_blank | 是否允许为空字符串 |
trim_whitespace | 是否移除两边的空白字符 |
max_value | 最小数值 |
min_value | 最大数值 |
字段的通用选项参数:
参数名称 | 说明 |
---|---|
read_only | 表明该字段仅用于序列化输出,默认False |
write_only | 表明该字段仅用于反序列化输入,默认False |
required | 表明该字段在反序列化时必须输入,默认True |
default | 反序列化时使用的默认值 |
miss | 序列化时使用的默认值 |
allow_null | 表明反序列化时该字段是否允许传入None,默认False |
validators | 表明反序列化时该字段使用的验证器函数 |
error_messages | 表明反序列化时如果验证出错了,返回错误错误信息的字典 |
label | 用于HTML展示API页面时,显示的字段名称。 如果不写,则默认采用模型的verbose_name,但是前提是当前序列化器继承ModelSerializer |
help_text | 用于HTML展示API页面时,显示的字段帮助提示信息 如果不写,则默认采用模型的help_text,但是前提是当前序列化器继承ModelSerializer |
三 创建Serializer对象
定义好Serializer类后,就可以创建Serializer对象了。Serializer的构造方法为:
序列化器(instance=None, data=empty, many=False, context=None, **kwargs)
# 说明:
1)序列化器用于序列化时,则需要将模型类对象传入instance参数
2)序列化器用于反序列化时,将要被反序列化的数据传入data参数
3)序列化器用于序列化时,当instance的值是一个QuerySet类型,则需要声明many=True
4)除了以上参数外,在构造Serializer对象时,还可通过context参数额外添加数据传入到序列化器中。
常见的写法:
serializer = Student1Serializer(instance=student) # 序列化单个模型对象为dict字典
serializer = Student1Serializer(instance=student_list, many=True) # 序列化多个模型对象为list列表
serializer = Student1Serializer(instance=student_list, context={'request': request}) # 如果传递数据到序列化器中,可以使用context # 说明
通过context参数附加的数据,可以通过Serializer对象的context属性获取。 1. 使用序列化器的时候一定要注意,序列化器声明了以后,不会自动执行,需要我们在视图中进行调用才可以。
2. 序列化器无法直接接收数据,需要我们在视图中实例化序列化器对象时把使用的数据通过instance传递过来。
3. 序列化器的字段声明类似于我们前面使用过的模型。
4. 开发restful api时,序列化器会帮我们把模型对象转换成字典
四 序列化器的使用
序列化器的使用分两个阶段:
在客户端请求时,使用序列化器可以完成对数据的反序列化。
在服务器响应时,使用序列化器可以完成对数据的序列化。
一 序列化
一 基本使用
from django.views import View
from .serializers import StudentSerializer
from stuapi.models import Student
from django.http.response import JsonResponse # Create your views here.
class Student1View(View):
def get1(self, request):
"""序列化器的基本使用:序列化单个模型对象为字典"""
student = Student.objects.first()
print(student)
# 把模型对象作为instance参数的值传递到序列化器中进行转换数据格式
serializer = StudentSerializer(instance=student)
print(serializer.data)
"""
{'id': 1, 'name': 'xiaoming', 'sex': True, 'age': 16, 'description': 'xxxxx'}
"""
return JsonResponse(serializer.data) """如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加**many=True**参数补充说明"""
def get(self, request):
"""序列化器的基本使用:序列化多个模型对象为列表"""
student_list = Student.objects.all()
print(student_list)
# 把模型列表作为instance参数传递到序列化器中进行数据格式转换
serializer = StudentSerializer(student_list, many=True)
print(serializer.data)
return JsonResponse(serializer.data, safe=False)
视图代码
二 反序列化
一 数据验证
使用序列化器进行反序列化时需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
验证成功,可以通过序列化器对象的validated_data属性获取数据。
1 定义字段类型和选项参数验证
在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。
from rest_framework import serializers
"""
rest_framework.serializers 是drf提供给开发者调用的序列化器模块
里面声明了所有的可用序列化器的基类,常用的有:
Serializer 序列化器基类,drf中所有的序列化器类都必须继承于 Serializer
ModelSerializer 模型序列化器基类,是序列化器基类Serializer的子类,在工作中,除了Serializer基类以外,最常用的序列化器类基类
""" class StudentSerializer(serializers.Serializer):
"""学生信息序列化器"""
# 1. 转换的字段声明
id = serializers.IntegerField(read_only=True) # 在序列化阶段使用,在反序列化阶段中被忽视掉
name = serializers.CharField(max_length=12, min_length=4, error_messages={
# 字段选项在反序列化阶段中校验字段如果失败的错误提示
# "选项名": "提示内容",
"min_length": "name字段的值必须至少{min_length}个字符",
"max_length": "name字段的值必须低于{max_length}个字符",
"required": "name字段是必填字段",
})
age = serializers.IntegerField(min_value=1, max_value=100, error_messages={
"min_value": "年龄太小了,必须大于或等于{min_value}",
"max_value": "年龄太大了,必须小于或等于{max_value}",
})
sex = serializers.BooleanField(default=True) # default=True 等价于设置当前字段为选填字段,默认值为True
description = serializers.CharField()
password = serializers.CharField() # 用户密码
re_password = serializers.CharField() # 确认密码 # 2. 如果当前序列化器继承的是ModelSerializer,则需要声明调用的模型信息
# class Meta:
# model = 模型
# fields = "__all__"
# fields = ["字段1","字段2",....] # 3. 验证代码的对象方法
# def validate(self, attrs): # 方法名validate是固定的,attrs就是客户端发送的数据,字典格式
# pass
# return attrs # def validate_<字段名>(self, data): # 方法名的格式必须以 validate_<字段名> 为名称,否则序列化器不识别!
# pass
# return data # 4. 模型操作的扩展方法
# def create(self, validated_data): # 添加数据操作,添加数据以后,就自动实现了从字典变成模型对象的过程
# pass
#
# def update(self, instance, validated_data): # 更新数据操作,更新数据以后,就自动实现了从字典变成模型对象的过程
# pass
sers/serialziers.py
from django.views import View
from .serializers import StudentSerializer
from stuapi.models import Student
from django.http.response import JsonResponse # Create your views here.
class Student1View(View):
def get1(self, request):
"""序列化器的基本使用:序列化单个模型对象为字典"""
student = Student.objects.first()
print(student)
# 把模型对象作为instance参数的值传递到序列化器中进行转换数据格式
serializer = StudentSerializer(instance=student)
print(serializer.data)
"""
{'id': 1, 'name': 'xiaoming', 'sex': True, 'age': 16, 'description': 'xxxxx'}
"""
return JsonResponse(serializer.data) def get2(self, request):
"""序列化器的基本使用:序列化多个模型对象为列表"""
student_list = Student.objects.all()
print(student_list)
# 把模型列表作为instance参数传递到序列化器中进行数据格式转换
serializer = StudentSerializer(student_list, many=True)
print(serializer.data)
return JsonResponse(serializer.data, safe=False) def get(self, request):
"""序列化器的基本使用:反序列化验证数据"""
# 模拟客户端提交过来的数据
data = {
# "name": "root",
"name": "xiaoming",
"age": 20,
"classmate": 303,
"description": "hello world",
"password": "123",
"re_password": "123",
} # 实例化序列化器用于反序列化
serializer = StudentSerializer(data=data)
# # 验证失败不会抛出异常
# ret = serializer.is_valid()
# if ret:
# print("验证通过!")
# print(serializer.validated_data) # 获取验证通过后的客户端提交的数据
# else:
# print("验证失败!获取验证错误的提示信息")
# print(serializer.errors)
# print(serializer.error_messages) # 验证失败则会抛出异常[最常用]
serializer.is_valid(raise_exception=True)
print("验证通过,验证结果数据:", serializer.validated_data)
return JsonResponse("ok", safe=False)
views.py
如果需要再补充定义验证行为,可以使用以下三种方法:
2 validate_字段名
校验指定字段数据的方法,serializers.py,代码
"""校验指定字段数据的方法"""
def validate_name(self, data): # 方法名的格式必须以 validate_<字段名> 为名称,否则序列化器不识别!
if data == "root":
raise serializers.ValidationError(detail=f"name字段的值不能是{data}", code="validate")
print("一旦出现异常,序列化器将返回异常给调用处,不会继续往下执行")
return data
视图代码,测试
def get(self, request):
"""序列化器的基本使用:反序列化验证数据"""
# 模拟客户端提交过来的数据
data = {
# "name": "root",
"name": "xiaoming",
"age": 20,
"classmate": 303,
"description": "hello world",
"password": "123",
"re_password": "123",
} # 实例化序列化器用于反序列化
serializer = StudentSerializer(data=data) # 验证失败则会抛出异常[最常用]
serializer.is_valid(raise_exception=True)
print("验证通过,验证结果数据:", serializer.validated_data)
return JsonResponse("ok", safe=False)
3 validate
在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证,如serializers.py,代码
"""同时校验多个字段的方法"""
def validate(self, attrs): # 方法名validate是固定的,attrs就是客户端发送的数据,字典格式
if attrs["password"] != attrs["re_password"]:
raise serializers.ValidationError(detail="对不起,密码与确认密码不一致!请重新填写", code="validate")
return attrs
视图代码,测试,同上
4 validators选项
在字段声明中添加validators选项参数,也可以补充验证行为函数,如serializers.py,代码
from rest_framework import serializers
"""
rest_framework.serializers 是drf提供给开发者调用的序列化器模块
里面声明了所有的可用序列化器的基类,常用的有:
Serializer 序列化器基类,drf中所有的序列化器类都必须继承于 Serializer
ModelSerializer 模型序列化器基类,是序列化器基类Serializer的子类,在工作中,除了Serializer基类以外,最常用的序列化器类基类
""" def check_desc(data):
"""
验证函数,通过字段声明的validators选项中作为列表成员传递使用
data: 当前要校验的字段的值
"""
if "hi" in data:
raise serializers.ValidationError(detail="个性签名中不能出现废话!", code="validators")
# 验证代码的最后,必须把本地校验的数据作为返回值返回给外界,否则serializer序列化器对象会丢失验证的数据
return data class StudentSerializer(serializers.Serializer):
"""学生信息序列化器"""
# 1. 转换的字段声明
id = serializers.IntegerField(read_only=True) # 在序列化阶段使用,在反序列化阶段中被忽视掉
name = serializers.CharField(max_length=12, min_length=4, error_messages={
# 字段选项在反序列化阶段中校验字段如果失败的错误提示
# "选项名": "提示内容",
"min_length": "name字段的值必须至少{min_length}个字符",
"max_length": "name字段的值必须低于{max_length}个字符",
"required": "name字段是必填字段",
})
age = serializers.IntegerField(min_value=1, max_value=100, error_messages={
"min_value": "年龄太小了,必须大于或等于{min_value}",
"max_value": "年龄太大了,必须小于或等于{max_value}",
})
sex = serializers.BooleanField(default=True) # default=True 等价于设置当前字段为选填字段,默认值为True
description = serializers.CharField(validators=[check_desc]) # validators=[验证函数名, 验证函数名....]
password = serializers.CharField() # 用户密码
re_password = serializers.CharField() # 确认密码 # 2. 如果当前序列化器继承的是ModelSerializer,则需要声明调用的模型信息
# class Meta:
# model = 模型
# fields = "__all__"
# fields = ["字段1","字段2",....] # 3. 验证代码的对象方法
"""同时校验多个字段的方法"""
def validate(self, attrs): # 方法名validate是固定的,attrs就是客户端发送的数据,字典格式
if attrs["password"] != attrs["re_password"]:
raise serializers.ValidationError(detail="对不起,密码与确认密码不一致!请重新填写", code="validate")
# 验证代码的最后,必须把本地校验的数据作为返回值返回给外界,否则serializer序列化器对象会丢失验证的数据
# 返回的验证数据如果被修改了,则会覆盖客户端提交的数据
# attrs["description"] = "hello!!!!"
return attrs """校验指定字段数据的方法"""
def validate_name(self, data): # 方法名的格式必须以 validate_<字段名> 为名称,否则序列化器不识别!
if data == "root":
raise serializers.ValidationError(detail=f"name字段的值不能是{data}", code="validate")
print("一旦出现异常,序列化器将返回异常给调用处,不会继续往下执行")
# 验证代码的最后,必须把本地校验的数据作为返回值返回给外界,否则serializer序列化器对象会丢失验证的数据
return data # 4. 模型操作的扩展方法
# def create(self, validated_data): # 添加数据操作,添加数据以后,就自动实现了从字典变成模型对象的过程
# pass
#
# def update(self, instance, validated_data): # 更新数据操作,更新数据以后,就自动实现了从字典变成模型对象的过程
# pass
serializers.py
视图代码,测试,同上
二 保存数据
前面的验证数据成功后,我们可以使用序列化器来完成数据反序列化的过程.这个过程可以把数据转成模型类对象。可以通过实现create()和update()两个方法来实现。serializers.py,代码
# 4. 模型操作的扩展方法
def create(self, validated_data): # 添加数据操作,添加数据以后,就自动实现了从字典变成模型对象的过程
"""
添加操作
validated_data:经过验证后的客户端数据
"""
student = Student.objects.create(
name=validated_data.get("name"),
age=validated_data.get("age"),
sex=validated_data.get("sex"),
classmate=validated_data.get("classmate"),
description=validated_data.get("description")
) # 注意,可以把新增的模型对象作为返回值返给serializer.save()
return student def update(self, instance, validated_data): # 更新数据操作,更新数据以后,就自动实现了从字典变成模型对象的过程
"""更新数据"""
if validated_data.get('name'):
instance.name = validated_data.get('name')
if validated_data.get('age'):
instance.age = validated_data.get('age')
if validated_data.get('sex') is not None:
instance.sex = validated_data.get('sex')
if validated_data.get('classmate'):
instance.classmate = validated_data.get('classmate')
if validated_data.get('description'):
instance.description = validated_data.get('description') instance.save() return instance
实现了上述两个方法后,在反序列化数据的时候,就可以通过序列化器的save()方法自动调用
serializer.save()
如果创建序列化器对象时没有传递instance参数,则调用序列化器内部的create()方法,相反,创建序列化器对象时传递了instance参数,则调用序列化器内部的update()方法。
视图代码,测试
def get4(self, request):
"""序列化器的基本使用:自动调用create添加数据"""
# 模拟客户端提交过来的数据
data = {
"name": "xiaoming",
"age": 20,
"classmate": 303,
"description": "hello world",
"password": "456",
"re_password": "456",
} serializer = StudentSerializer(data=data)
serializer.is_valid(raise_exception=True)
serializer.save()
# save源代码中,根据实例化序列化器时是否传递了instance,
# 如果传递了instance参数,则serializer.save()会自动调用序列化器内部的update,并把instance与验证后的validated_data作为参数
# 如果没有传递instance参数,则serializer.save()会自动调用序列化器内部的create方法,并把验证后的validated_data作为参数 # 使用serializer.data实现序列化操作
return JsonResponse(serializer.data, status=201, safe=False) def get(self, request):
"""序列化器的基本使用:自动调用update修改数据"""
# 模拟客户端提交过来的数据
data = {
"name": "小明同学",
"age": 20,
"classmate": 305,
"description": "hello world",
"password": "456",
"re_password": "456",
} # 查询数据库,得到要修改的模型对象
student = Student.objects.get(pk=9) serializer = StudentSerializer(instance=student, data=data)
serializer.is_valid(raise_exception=True)
serializer.save()
# save源代码中,根据实例化序列化器时是否传递了instance,
# 如果传递了instance参数,则serializer.save()会自动调用序列化器内部的update,并把instance与验证后的validated_data作为参数
# 如果没有传递instance参数,则serializer.save()会自动调用序列化器内部的create方法,并把验证后的validated_data作为参数 # 使用serializer.data实现序列化操作
return JsonResponse(serializer.data, status=201, safe=False)
三 附加说明
1) 在对序列化器进行save()保存数据时,可以给序列化器的save方法额外传递数据,这些数据可以在create()和update()中的validated_data参数获取到,用于补充数据给模型的
serializer.save(sex=False) # 可以在save中,传递一些不需要验证的数据到模型里面
2)默认序列化器必须传递所有required的字段,否则会抛出验证异常。但是我们可以使用partial参数来允许部分字段更新
def get(self, request):
"""序列化器的基本使用:自动调用update修改数据"""
# 模拟客户端提交过来的数据
data = {
"name": "小明同学",
"classmate": 305,
"description": "hello world",
"password": "456",
"re_password": "456",
} # 查询数据库,得到要修改的模型对象
student = Student.objects.get(pk=9) # partial=True 表示 对不存在的数据或客户端没有提供的数据,不需要按序列化器的字段列表进行验证。
serializer = StudentSerializer(instance=student, data=data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save(sex=False)
# save源代码中,根据实例化序列化器时是否传递了instance,
# 如果传递了instance参数,则serializer.save()会自动调用序列化器内部的update,并把instance与验证后的validated_data作为参数
# 如果没有传递instance参数,则serializer.save()会自动调用序列化器内部的create方法,并把验证后的validated_data作为参数 # 使用serializer.data实现序列化操作
return JsonResponse(serializer.data, status=201, safe=False)
三 模型类序列化器
如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
ModelSerializer与常规的Serializer的用法相同,但额外提供了:
基于模型类自动生成一系列序列化器字段
基于模型类自动为Serializer生成validators,比如unique_together
ModelSerializer默认包含了create()和update()的代码实现
️ ModelSerializer内置了create与update方法,所以ModelSerializer在使用过程中,实际上不需要我们手写create与update方法的。而Serializer的源码中并没有内置create与update方法,所以我们如果要让Serializer实现数据保存功能,则务必实现create与update方法。
一 定义模型类序列化器
serializers.py,代码
from rest_framework import serializers
class StudentModelSerializer(serializers.ModelSerializer):
"""学生信息模型类序列化器"""
# 字段声明中可以覆盖从模型那边导入的字段声明[没有必要重写,只需要extra_kwargs中补充验证选项即可]
# age = serializers.IntegerField(min_value=10) # 同时,也可以声明一些模型中没有的字段
password = serializers.CharField(write_only=True)
re_password = serializers.CharField(write_only=True) class Meta:
model = Student # 必填
# 务必把模型导入过的字段与上面的字段全部填入到fields的属性值,否则报错!!
fields = ["id", "name", "age", "sex", "classmate", "password", "re_password"]
# fields = "__all__" # 从模型中引入所有的字段序列化器中
read_only_fields = ["id", "sex"] # 只读字段列表,设置在这里的字段只会在序列化时使用到,不会被用于反序列化
extra_kwargs = {
"age": {"min_value": 10, "max_value": 100},
"name": {"min_length": 4, "max_length": 16, "error_messages": {
"min_length": "name字段的值长度必须是4个字符以上"
}},
} def validate(self, attrs):
"""验证多个字段"""
if attrs["password"] != attrs["re_password"]:
raise serializers.ValidationError(detail="密码和确认密码不一致") # 可以在验证完成以后,把数据库中不需要的字典从attrs中移除
attrs.pop("password")
attrs.pop("re_password") # 务必把验证后的内容返回给客户端
return attrs
Meta类里面的必填属性有2个:
model:指定当前序列化器类绑定的哪个模型类
fields:指定导入模型类的哪些字段到当前序列化器中作为序列化字段
视图代码,测试:
def get6(self,request):
"""模型类序列化器的基本使用:序列化1个模型"""
student = Student.objects.first()
serializer = StudentModelSerializer(instance=student)
print(serializer)
return JsonResponse(serializer.data) def get7(self,request):
"""模型类序列化器的基本使用:序列化多个模型"""
student_list = Student.objects.all()
serializer = StudentModelSerializer(instance=student_list, many=True)
return JsonResponse(serializer.data, safe=False) def get(self,request):
"""模型类序列化器的基本使用:反序列化验证数据"""
# 模拟客户端提交过来的数据
data = {
"name": "hello",
"classmate": 305,
"age": 20,
"description": "hello world",
"password": "456",
"re_password": "456",
}
serializer = StudentModelSerializer(data=data)
print(serializer)
serializer.is_valid(raise_exception=True)
serializer.save()
return JsonResponse(serializer.data, safe=False)
二 指定字段
1)使用fields来明确字段,__all__
表名包含所有字段,也可以写明具体哪些字段,如
class StudentModelSerializer(serializers.ModelSerializer):
"""学生信息序列化器"""
# 2. 如果当前序列化器继承的是ModelSerializer,则需要声明调用的模型信息
# 必须给Meta声明2个属性
class Meta:
model = Student # 必填
fields = "__all__" # 必填,可以是字符串和列表/元组,字符串的值只能是"__all__"表示返回所有字段
2)使用exclude可以明确排除掉哪些字段不要从模型类导入过来,少用,与fields互斥的。
class StudentModelSerializer(serializers.ModelSerializer):
"""学生信息序列化器"""
# 1. 转换的字段声明
# 字段名 = 字段类型(选项=选项值)
nickname = serializers.CharField(read_only=True) # 2. 如果当前序列化器继承的是ModelSerializer,则需要声明调用的模型信息
# 必须给Meta声明2个属性
class Meta:
model = Student # 必填
exclude = ['description'] # 排除,
3)显示指明字段,如:
class StudentModelSerializer(serializers.ModelSerializer):
"""学生信息序列化器"""
# 1. 转换的字段声明
# 字段名 = 字段类型(选项=选项值)
nickname = serializers.CharField(read_only=True) # 2. 如果当前序列化器继承的是ModelSerializer,则需要声明调用的模型信息
# 必须给Meta声明2个属性
class Meta:
model = Student # 必填
fields = ["id", "name", "age", "sex","nickname"] # 必填,可以是字符串和列表/元组
4)指明指定字段,如:
可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段
class StudentModelSerializer(serializers.ModelSerializer):
"""学生信息序列化器"""
# 1. 转换的字段声明
# 字段名 = 字段类型(选项=选项值)
nickname = serializers.CharField(read_only=True) # 2. 如果当前序列化器继承的是ModelSerializer,则需要声明调用的模型信息
# 必须给Meta声明2个属性
class Meta:
model = Student # 必填
fields = ["id", "name", "age", "sex","nickname"] # 必填,可以是字符串和列表/元组,字符串的值只能是"__all__"表示返回所有字段
read_only_fields = ["id","sex"] # 选填,只读字段列表,表示设置这里的字段只会在序列化阶段采用
三 添加额外参数
我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
class StudentModelSerializer(serializers.ModelSerializer):
"""学生信息序列化器"""
# 1. 转换的字段声明
# 字段名 = 字段类型(选项=选项值)
nickname = serializers.CharField(read_only=True) # 2. 如果当前序列化器继承的是ModelSerializer,则需要声明调用的模型信息
# 必须给Meta声明2个属性
class Meta:
model = Student # 必填
fields = ["id", "name", "age", "sex","nickname"] # 必填,可以是字符串和列表/元组,字符串的值只能是"__all__"表示返回所有字段
read_only_fields = ["id","sex"] # 选填,只读字段列表,表示设置这里的字段只会在序列化阶段采用
extra_kwargs = { # 选填,字段额外选项声明
"age": {
"min_value": 5,
"max_value": 20,
"error_messages": {
"min_value": "年龄的最小值必须大于等于5",
"max_value": "年龄的最大值必须小于等于20",
}
},
}
四 附
什么时候声明的序列化器需要继承序列化器基类Serializer,什么时候继承模型序列化器类ModelSerializer?
看客户端提交的数据是否与数据库模型相关,如果是则使用ModelSerializer,不是则使用Serializer,当然,即便和数据库相关,我们偏要使用Serializer,也没有问题。
继承序列化器类Serializer
字段声明
验证
添加/保存数据功能 继承模型序列化器类 ModelSerializer
字段声明[可选,看需要]
Meta声明[必填]
验证
添加/保存数据功能[可选,看需要,例如一次性添加数据到多个模型中]
DRF的序列化器Serializer的更多相关文章
- 066.Python框架DRF之序列化器Serializer
一 序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 反序列化,把客户端发送过来的数据,经过request以后变成 ...
- drf之序列化器的使用
一.序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经 ...
- Cf序列化器-Serializer解析
Cf序列化器-Serializer 定义序列化器 Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Seri ...
- day82 序列化器-Serializer
目录 一.序列化器的基本功能 二.定义序列化器 三.创建Serializers对象 四.序列化器的使用 1 序列化 2 反序列化 2.1 数据验证(类比forms组件) 2.2 数据保存 一.序列化器 ...
- 第三章、drf框架 - 序列化组件 | Serializer
目录 第三章.drf框架 - 序列化组件 | Serializer 序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer( ...
- DRF 序列化器-Serializer (2)
作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器 ...
- DRF中序列化器定义及使用
首先需要明白序列化和反序列化的定义及作用: 序列化是将程序语言转换为JSON/XML; 反序列化是将JSON/XML转换为程序语言; 对应到Django中,序列化即把模型对象转换为字典形式, 在返回给 ...
- drf的序列化器
三流 import sys #标准输出流 sys.stdout.write('123\n') sys.stdout.write('456\n') #标准输入流 res=sys.stdin.readli ...
- drf框架 - 序列化组件 | Serializer
序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 序列化与反序列化 序列化: 将对象序列化成字符串用户传输 ...
- 写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用
写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用 一.了解什么是DRF DRF: Django REST framework Django REST framew ...
随机推荐
- docker打包nginx
nginx镜像 localtime为/etc/localtime文件 给容器限定日志打印时间为北京时间 FROM nginx:stable-alpine MAINTAINER geyanan gey ...
- JS篇(009)-javascript 对象的几种创建方式
答案: 第一种:Object 构造函数创建 var Person = new Object(); Person.name = "Nike"; Person.age = 29; 这行 ...
- 数据驱动DDT(Data-Driven Tests):测试数据的参数化
准备第三方库: 首先安装ddt库,其次在脚本中引入ddt 打开官网 https://pypi.org/project/ddt/ from ddt import ddt,data,unpack @ddt ...
- 升级adb
adb 是没有自动升级的命令的,如果想要更新adb的版本,需要在网上找到自己想要的版本进行更新. 为什么要更新呢? 肯定是在使用中遇到了什么问题必须升级版本才能解决,如果不影响使用,那都无所谓.这里提 ...
- 西瓜书3.3 尝试解题(python)对率回归 极大似然估计
数据如下: x01=[0.697,0.774,0.634,0.608,0.556,0.403,0.481,0.437,0.666,\ 0.243,0.245,0.343,0.639,0.657,0.3 ...
- Vue-数据代理
Vue中的数据代理 数据代理定义 所谓数据代理,就是通过一个对象代理对另一个对象中的属性的操作(读/写).说白了就是操作一个对象上的属性可以读取和修改另一个对象上的属性,这种关系就叫做数据代理. 在V ...
- 1=C到底是哪个C
- 反序列化 sqlserver 中的 sysdiagrams,找到其中包含的表的信息
转载于:Script SQL Server 2005 diagrams to a file - CodeProject /** <summary> Based on ufn_Varbina ...
- [杂谈吐槽]UE国内社区环境
此篇博客是我个人想法,当然也是不争的事实,如果您有意见,那您也是我说那些人其中的一员. --此部分为社区环境差最恶劣的原因-- 国内的虚幻社区环境可以说不能再烂了,虚幻商城和虚幻引擎的蓝图是非常强大的 ...
- html-list
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...