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
原文地址:https://www.cnblogs.com/liuwei0824/p/8464476.html