天天看点

django rest framework的序列化与反序列化序列化和反序列化打印序列化前的类型和序列化的类型

序列化和反序列化

序列化是服务端返数据给前端的时候,将模型类对象转化成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序列化作用是相同的,都是用来实现序列化和反序列化的,但是有几个不同点:

  1. 它可以基于模型类自动生成序列化器字段

    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