zoukankan      html  css  js  c++  java
  • python-django rest framework框架之序列化

    序列化与反序列化:
                对象 -> 字符串   序列化
                字符串 -> 对象   反序列化
    rest framework序列化+Form
            
            目的:
                解决QuerySet序列化问题
            功能:解析 和 过滤
                - QuerySet类型 -> 列表、字典
                - 请求验证
            序列化:
                a. 基本操作:
                    class UsersSerializer(serializers.Serializer):    #定义这个类相当于一个序列化模板
                        name = serializers.CharField()
                        pwd = serializers.CharField()
                
                            
                    class UsersView(APIView):
                        def get(self,request,*args,**kwargs):
                            self.dispatch
                            # 方式一:
                            # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
                            # return Response(user_list)
    
                            # 方式二之多对象
                            # user_list = models.UserInfo.objects.all()
                            # ser = UsersSerializer(instance=user_list,many=True)
                            # return Response(ser.data)
    
                            # 方式二之单对象
                            user = models.UserInfo.objects.all().first()
                            ser = UsersSerializer(instance=user, many=False)
                            return Response(ser.data)
    
                b. 跨表
                    class UsersSerializer(serializers.Serializer):
                        name = serializers.CharField()
                        pwd = serializers.CharField()
                        group_id = serializers.CharField()
                        xxxx = serializers.CharField(source="group.title")
                        x1 = serializers.CharField(source="group.mu.name")
    
    
    
                    class UsersView(APIView):
                        def get(self,request,*args,**kwargs):
                            self.dispatch
                            # 方式一:
                            # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
                            # return Response(user_list)
    
                            # 方式二之多对象
                            user_list = models.UserInfo.objects.all()
                            ser = UsersSerializer(instance=user_list,many=True)
                            return Response(ser.data)
    
                c. 复杂序列化
                    解决方案一:     manytomany  自定义一个类,继承CharField,重写to_representation方法
                        class MyCharField(serializers.CharField):
    
                            def to_representation(self, value):
                                data_list = []
                                for row in value:
                                    data_list.append(row.name)
                                return data_list
    
                        class UsersSerializer(serializers.Serializer):
                            name = serializers.CharField() # obj.name
                            pwd = serializers.CharField()  # obj.pwd
                            group_id = serializers.CharField() # obj.group_id
                            xxxx = serializers.CharField(source="group.title") # obj.group.title
                            x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
                            # x2 = serializers.CharField(source="roles.all") # obj.mu.name
                            x2 = MyCharField(source="roles.all") # obj.mu.name
        
                    解决方案二:
                        class MyCharField(serializers.CharField):
                            def to_representation(self, value):
                                return {'id':value.pk, 'name':value.name}
    
                        class UsersSerializer(serializers.Serializer):
                            name = serializers.CharField() # obj.name
                            pwd = serializers.CharField()  # obj.pwd
                            group_id = serializers.CharField() # obj.group_id
                            xxxx = serializers.CharField(source="group.title") # obj.group.title
                            x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
                            # x2 = serializers.CharField(source="roles.all") # obj.mu.name
                            x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name
    
                    解决方案三(*):
                        class UsersSerializer(serializers.Serializer):
                            name = serializers.CharField() # obj.name
                            pwd = serializers.CharField()  # obj.pwd
                            group_id = serializers.CharField() # obj.group_id
                            xxxx = serializers.CharField(source="group.title") # obj.group.title
                            x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
                            # x2 = serializers.CharField(source="roles.all") # obj.mu.name
                            # x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name
                            x2 = serializers.SerializerMethodField()
    
                            def get_x2(self,obj):
                                obj.roles.all()
                                role_list = obj.roles.filter(id__gt=1)
                                data_list = []
                                for row in role_list:
                                    data_list.append({'pk':row.pk,'name':row.name})
                                return data_list
        
                    
                    以上三种都是使用相同的视图:
                        class UsersView(APIView):
                            def get(self,request,*args,**kwargs):
                                self.dispatch
                                # 方式一:
                                # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
                                # return Response(user_list)
    
                                # 方式二之多对象
                                user_list = models.UserInfo.objects.all()
                                # [obj1,obj2,obj3]
                                ser = UsersSerializer(instance=user_list,many=True)
                                return Response(ser.data)
    
    
                d. 基于Model
                
                    class UsersSerializer(serializers.ModelSerializer):
                        class Meta:
                            model = models.UserInfo
                            fields = "__all__"
                            # fields = ['name', 'pwd','group']
                            depth = 1
    
    
                    class UsersView(APIView):
                        def get(self,request,*args,**kwargs):
                            self.dispatch
                            # 方式一:
                            # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
                            # return Response(user_list)
    
                            # 方式二之多对象
                            user_list = models.UserInfo.objects.all()
                            # [obj1,obj2,obj3]
                            ser = UsersSerializer(instance=user_list,many=True)
                            return Response(ser.data)
                
                
                e. 生成URL
                                    
                    class UsersSerializer(serializers.ModelSerializer):
                        group = serializers.HyperlinkedIdentityField(view_name='detail')
                        class Meta:
                            model = models.UserInfo
                            fields = "__all__"
                            fields = ['name', 'pwd','group']
                            depth = 1
    
    
                    class UsersView(APIView):
                        def get(self,request,*args,**kwargs):
                            self.dispatch
                            # 方式一:
                            # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
                            # return Response(user_list)
    
                            # 方式二之多对象
                            user_list = models.UserInfo.objects.all()
                            # [obj1,obj2,obj3]
                            ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
                            return Response(ser.data)
        
        
                f. 全局生成URL
                                    
                    class UsersSerializer(serializers.HyperlinkedModelSerializer):
                        class Meta:
                            model = models.UserInfo
                            fields = "__all__"
    
                            # fields = ['id','name','pwd']
    
                    class UsersView(APIView):
                        def get(self,request,*args,**kwargs):
                            self.dispatch
                            # 方式一:
                            # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
                            # return Response(user_list)
    
                            # 方式二之多对象
                            user_list = models.UserInfo.objects.all()
                            # [obj1,obj2,obj3]
                            ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
                            return Response(ser.data)
        
            
            请求数据验证:
            
                a.         
                    class PasswordValidator(object):
                        def __init__(self, base):
                            self.base = base
    
                        def __call__(self, value):
                            if value != self.base:
                                message = '用户输入的值必须是 %s.' % self.base
                                raise serializers.ValidationError(message)
    
                        def set_context(self, serializer_field):
                            """
                            This hook is called by the serializer instance,
                            prior to the validation call being made.
                            """
                            # 执行验证之前调用,serializer_fields是当前字段对象
                            pass
    
                    class UsersSerializer(serializers.Serializer):
                            name = serializers.CharField(min_length=6)
                            pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('666')])
    
                
                b. 
                    class PasswordValidator(object):
                        def __init__(self, base):
                            self.base = base
    
                        def __call__(self, value):
                            if value != self.base:
                                message = '用户输入的值必须是 %s.' % self.base
                                raise serializers.ValidationError(message)
    
                        def set_context(self, serializer_field):
                            """
                            This hook is called by the serializer instance,
                            prior to the validation call being made.
                            """
                            # 执行验证之前调用,serializer_fields是当前字段对象
                            pass
    
                    class UsersSerializer(serializers.ModelSerializer):
                        class Meta:
                            model = models.UserInfo
                            fields = "__all__"
                            extra_kwargs = {
                                'name': {'min_length': 6},
                                'pwd': {'validators': [PasswordValidator(666), ]}
                            }
    
               - 钩子函数
                        def validate_字段(self,validated_value):
                            可以抛出异常 raise ValidationError(detail='xxxxxx')
                            可以返回正确的值 return validated_value    使用:
    class UsersView(APIView): def get(self,request,*args,**kwargs): self.dispatch # 方式一: # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title") # return Response(user_list) # 方式二之多对象 user_list = models.UserInfo.objects.all() # [obj1,obj2,obj3] ser = UsersSerializer(instance=user_list,many=True,context={'request':request}) return Response(ser.data) def post(self,request,*args,**kwargs): ser = UsersSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data) else: print(ser.errors) return Response('...')

     钩子函数源码:

    class BaseSerializer(Field):
        def is_valid(self, raise_exception=False):
            
            if not hasattr(self, '_validated_data'):
                try:
                    #执行run_validation方法
                    self._validated_data = self.run_validation(self.initial_data)
                except ValidationError as exc:
                    self._validated_data = {}
                    self._errors = exc.detail
                else:
                    self._errors = {}
    
            return not bool(self._errors)
    class Serializer(BaseSerializer):
        def run_validation(self, data=empty):
            #执行to_internal_value 方法
            value = self.to_internal_value(data)
            
            return value
    class Serializer(BaseSerializer):
        def to_internal_value(self, data):
            
            for field in fields:
                #这步就是在找钩子函数
                validate_method = getattr(self, 'validate_' + field.field_name, None)
                primitive_value = field.get_value(data)
                try:
                    validated_value = field.run_validation(primitive_value)
                    #在这步执行钩子函数
                    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)
                except SkipField:
                    pass
                else:
                    set_value(ret, field.source_attrs, validated_value)
    
            if errors:
                raise ValidationError(errors)
    
            return ret
  • 相关阅读:
    NgModelController: $setViewValue,$render,Formatter, Parser
    #!/usr/bin/env python与#!/usr/bin/python的区别
    post发送数据 mypost input 改变事件
    post发送 ArrayBuffer
    C# 字符串到字节数组,字节数组转整型
    C# WebKitBrowser 设置内容
    C# Tuple 创建一个新二元集合
    C# 时间对比
    C# 控件调整
    C# invoke和begininvoke的用法 __委托
  • 原文地址:https://www.cnblogs.com/liuwei0824/p/8464476.html
Copyright © 2011-2022 走看看