序列化和反序列化
序列化是服务端返数据给前端的时候,将模型类对象转化成josn,一般用于get请求
反序列化是接收前端json数据后反序列化成后端可操作的数据,一般用于post等从前端获取数据的请求。从前端获取到数据后需要先校验is_valid,验证数据是否是符合规范的,是否可以转化成类模型对象,正确返回true,错误返回false。
delete不需要序列化器
josn和字典的区别:
josn是一种数据类型,键值必须用双引号引
字典是一种数据结构 以键值对的形式存在
打印序列化前的类型和序列化的类型
views
# 我们来看看序列化前的数据类型,序列化后的数据类型,还有序列化器对象.data取到的数据类型
def show(request):
users = User.objects.all()
usersser = UserSerializer(users, many=True)
print('users======>', users)
print('usersser=========>', usersser)
print('usersser.data=========>', usersser.data)
user1 = User.objects.get(pk=1)
user1ser = UserSerializer(user1)
print('user1=========>', user1)
print('user1ser======>', user1ser)
print('user1ser.data======>', user1ser.data)
return JsonResponse(user1ser.data)
打印结果
# 查询的结果里面有多条数据时候的返回 User.objects.all()
users======> <QuerySet [<User: User object (1)>, <User: User object (2)>]>
# QuerySet这是个查询结果集,里面是一个个的模型类对象
usersser=========> UserSerializer(<QuerySet [<User: User object (1)>, <User: User object (2)>]>, many=True):name = CharField()
# 这是个序列化器对象
usersser.data=========> [OrderedDict([('name', 'ybc')]), OrderedDict([('name', 'ybc')])]
# 必须通过序列化器对象.data 才能拿到这个字典(OrderedDict是python的高级数据类型,是有序字典)
# return JsonResponse(usersser.data) 通过JsonResponse就可以自动转成前端想要的json数据
## 如果模型类里写了
def __str__(self):
return self.name
# 那么返回的:
users======> <QuerySet [<User: ybc>, <User: ybc>]>
usersser=========> UserSerializer(<QuerySet [<User: ybc>, <User: ybc>]>, many=True):
name = CharField()
usersser.data=========> [OrderedDict([('name', 'ybc')]), OrderedDict([('name', 'ybc')])]
# 查询的结果里面只有一条数据时候的返回 User.objects.filter(pk=1)
user1=========> User object (1)
user1ser======> UserSerializer(<User: User object (1)>):
name = CharField()
user1ser.data======> {'name': 'ybc'}
反序列化的东西比较多
# views.py
class UserViews(View):
def post(self,request):
data = json.loads(request.body) # 把request.body解析成json,原来的request.body是b'{\n\t"name":"\xas\asd\sas2"}这种的
serobj = UserSerializer(data=data) # 反序列化用data,序列化用instance,可以不写,默认传的就是instance
serobj.is_valid() # 验证数据
serializer.validated_data # 可以拿到通过的数据
serializer.errors # 可以拿到错误的信息
"""
验证数据有2种方法:
1.自动验证数据,和序列化器的字段(包括字段里面的约束,例如max_lenght=10这种)必须一样。
2.手动的在序列化器里添加验证规则:validate() 验证所有字段, validate()_字段名 验证单个字段)通过则有数据,没通过就是空,而且有错误信息.
"""
# serlalizers.py
# 在序列化器中自定义验证(注意优先级是单个字段验证在前,多个字段验证在后):
class UserSerializer(serializers.Serializer);
name = serializers.CharField(max_lenght=20)
age = serializers.IngerField(max_value=120)
# 单个字段的验证
def validate_name(self, giao):
if giao == '小阿giao':
raise serializers.ValidationError('对不起,我们不收小啊giao)
return giao # 注意返回的是不符合规定的那个数据,如果不返回,这个数据就永远丢失了
# 验证所有字段(一般可以用于注册时密码和确认密码的字段,或者联合验证)
def validate(self,attr):
if attr.get('name') > 50 and attr.get('name') == '老王':
raise serializers.ValidationError('对不起,我们不收大于50岁的老王)
return attr
# 全局字段验证函数(只能用于验证一个字段的数据)
def check_class_num(data):
if data == '200':
raise serializers.ValidationError('对不起,年龄太大了')
return data
class UserSerializer(serializers.Serializer):
# 之后把可以把这个全局验证函数加到字段约束中
age = serializers.IngerField(max_value=120, validators=[check_class_num])
反序列化操作数据库,数据操作成功后,把视图中对模型的操作拿到序列化中去做,通过序列化完成数据的更新和添加
# 使用update和create
class UserSerializer(serializers.Serializer);
name = serializers.CharField(max_lenght=20)
age = serializers.IngerField(max_value=120)
def create(self, validated_data): # validated_data是自带的参数,序列化器帮忙传的,就是验证完的数据
# 这里的写法和视图中没什么区别,只是拿到序列化器中来写了,需要在上面导入模型类 import User
# 本来validated_data是{'name':'ybc','age':18}, **打散,之后的validated_data是 nam=ybc, age=18
result = User.objects.create(**validated_data)
# 把添加的数据返回给函数调用处
return result
def update(self, instance, validated_data):
instance.name = validated_data.get('name')
instance.age = validated_data.get('age')
instance.save() # 模型的保存
return instance
# 这时候在views.py中save()
class UserViews(View):
def post(self,request):
data = json.loads(request.body)
serobj = UserSerializer(data=data)
serobj.is_valid()
# 执行数据库操作,save源码会根据实例化序列器对象中是否传递instance而自动调用的create或者update方法,如果没有传递,就是create方法,此处没传,所以是create
serobj.save() # save()存数据库的同时是有返回值的,可以用.data获取 (serobj.data)
return HttpResponse('创建完成')
def put(self,request):
# 想要修改数据,就要先获取到要更新字段的模型对象,这个data里有得一个没变的查询条件,假如就是id没变
ddata = json.loads(request.body)
# 获取到这个没变化的id,用来查询到这个id对应的模型对象
id = ddata.get('id') # 获取前端传来的参数
# 拿到这个id对应的模型对象
user = User.objects.get(pk=id)
# instance里传的是ddata里获取到的id对应的对象,data里传的是前端传来的修改后的数据
userser = UserSerializer(instance=user, data=ddata)
userser.is_valid()
# 执行数据库操作【自动调用的create或者update方法】,此处是update
userser.save()
return HttpResponse('更新完成')
反序列化的额外参数
serilalizer = UserSerializer(instance=xxxx, data=xxxx, partial=True)
# 实例化序列化器的时候,partial=True表示设置验证客户端上传来的部分数据,没有上传的字段可以不验证,直接忽略不管,还是会通过校验。
serilaizer.save(own=request.user)
# save进行保存时可以传递额外的参数,这些数据可以在create()和Update()中的validated_data参数中获取到
# 例如:request.user是django中记录当前用户的模型对象
某个字段,获取的时候用的到,上传时用不到怎么写序列化器
# 假如:get请求,我想要给前端返回id, name, age, 我就要在序列化器中写这个字段,但是post请求的时候,
# 我是不需要传id这个字段的,因为他是自增主键,传就会报错,该怎么办呢?使用read_only = True
class UserSerialize(serialiers.Serializer):
# read_only=True让这个字段只在序列化时(get)生效,反序列化(post等)时被忽略
# 与其相反的是write_only 一般会用在密码。登录时会收他的密码,但是返回他的信息的时候不会给他返回密码
id = serializers.IntegerField(read_only=True)
模型类序列化器 ModelSerializer
和常规的Serializer序列化作用是相同的,都是用来实现序列化和反序列化的,但是有几个不同点:
它可以基于模型类自动生成序列化器字段
2.基于模型类自动为Serializer生成validaters
3.直接包含create()和update(),不用自己写
class UserModelSerializer(serializers.ModelSerializer):
# 也可以像Serializer一样自己写字段,但是一般都不自己写,直接用原类自动生成
# 不过可以自定义字段, 这个字段模型里可以没有, 但是下面的fields=[]中要加上
token = Serializer.CharField(read_only=True, defult='abc')
class Meta:
model = User
fields = ['id', 'name' ,'age','token']
# fields = '__all__'
# exclude = ['',''] 除了这里的字段都返回,一般和all联用
# read_only_fields = ['',''] 批量设置read_only,只能设置模型中的,模型外的自定义字段无效,例如上面的token
"""
# 添加额外的参数,假如在age字段中再加上个最小值1
extra_kwargs = {
'age':{'min_value':1}
}
"""
# 也可以像上面的Serializer里一样手写验证
def validate_name(self, giao):
if giao == '小阿giao':
raise serializers.ValidationError('对不起,我们不收小啊giao)
return giao