zoukankan      html  css  js  c++  java
  • RESTFrame序列化问题

    序列化主要两个功能:

      1.用于对用户请求数据进行验证;

      2.对于数据库中的数据(queryset类型、model对象)进行序列化。

    一.对于后端程序从数据库拿到的数据(queryset、model对象)进行序列化

    models.py  # 表结构
    
    from django.db import models
    
    class Menu(models.Model):
        name = models.CharField(max_length=32)
    
    
    class Group(models.Model):
        title = models.CharField(max_length=32)
        mu = models.ForeignKey(to='Menu',default=1)
    
    class UserInfo(models.Model):
        name = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
    
        group = models.ForeignKey('Group')
        roles = models.ManyToManyField('Role')
    
    
    class Role(models.Model):
        name = models.CharField(max_length=32)

    以下是视图部分内容

    ########### 1.根据model表来序列化########################
    
    class UserSerializer(serializers.ModelSerializer):   # 继承自ModelSerializer类
        '''序列化数据的类,根据model表来获取字段'''
        x1 = serializers.CharField(source='name')  # 自定义字段,必须定义source
        class Meta:
            model = models.UserInfo
            # fields = '__all__'
            fields = ['name','pwd','group','x1']
            depth = 3    # 此字段表示查看嵌套几层的数据,不建议太大,性能损耗
    
    
    class UserView(APIView):
        '''用户相关视图'''
    
        def get(self,request,*args,**kwargs):
            user_list = models.UserInfo.objects.all()  # 从数据库拿到的query类型数据
            ser = UserSerializer(instance=user_list,many=True)    # 序列化的类,拿到一个对象
            print(ser.data)   # 序列化之后的json格式的数据
            return Response(ser.data)
    ####### 2.自己定义要序列化哪些字段 含:单表、一对多、多对多关系###########
    
    class MyCharField(serializers.CharField):
        "自定义模板中需要序列化字段的类,目的是自定制多对多关系中的返回值"
        def to_representation(self, value):
            # value代表,当前user对象关联的对象
            role_list = []
            for each in value:
                role_list.append(each.name)
            return role_list
    
    # 建立一个继承自serializers.Serializers的类,这种需要自己定义需要序列化的字段
    class UserSerializer(serializers.Serializer):
        "相当于建立一个序列化的模板,来规定需要的字段"
        # 单表中的字段
        id = serializers.CharField()  # obj.id (要是没有写source=xxx,就会执行obj.id)
        name = serializers.CharField()
        pwd =serializers.CharField()
    
        #跨表查询(多对一)
        group = serializers.CharField(source='group.title')  # source拿到当前对象的group属性的,
        menu_ttile = serializers.CharField(source='group.mu.name')
        menu_id = serializers.CharField(source='group.mu.id')    # 字符串内部做判断,可执行,则会执行
    
        # 多对多(自定制当前字段序列化之后返回中的内容)
        # role_list = serializers.CharField(source='roles.all')
        # 这种,在最后显示的时候,只能做成这样子 "role_list": "<QuerySet [<Role: Role object>, <Role: Role object>]>"
    
        # 方法1:定制to_representation方法
        # 针对上种情况,定制返回值,继承自(serializers.CharField)
        # role_list = MyCharField(source='roles.all')   # 看上边自定制的类MyCharField,其中重写了to_representation方法
    
        # 方法2:(其实返回的内容,还是需要自定义MyCharField()类定制返回的值,只是value指定每个role对象,)
        # role_list = serializers.ListField(child=serializers.CharField(),source='roles.all')
    
        # 方法3:(也需要自定制get_字段名,定义此子字段返回值,定制性更好,=====推荐使用====)
        role_list = serializers.SerializerMethodField()
    
        def get_role_list(self,obj):# obj就是当前user对象
            li = []
            roles_list = obj.roles.filter(id=1)  # 这里可以添加过滤的信息
            roles_list = obj.roles.all()
            for i in roles_list:
                li.append({'id':i.id,'name':i.name})
            return li
    
    
    
    class UserView(APIView):
    
        def get(self,request,*args,**kwargs):
            user_list = models.UserInfo.objects.all()       # 从数据库拿到的数据
            ser = UserSerializer(instance=user_list,many=True)
            print(ser.data)
            return Response(ser.data)

    二、对于前端POST提交的数据库进行验证,类似与form验证

    这个也是两种情况,类似与序列化,一种是根据表来做,另一种是细化到字段

    ########### 序列化功能二:对于请求数据做验证#############################
    
    class PassworValidator():
        '''自定义验证密码的验证规则类'''
        def __init__(self,base):      # base,就是验证规则,可以定义为正则表达式,或者是一个函数吧。
        # def __init__(self):      # base,就是验证规则,可以定义为正则表达式,或者是一个函数吧。
            self.base = base
    
        def __call__(self, value):   # 调用的时候,会执行__call__方法,value,就是前段post提交过来的数据
            '''在这个函数中做验证,然后返回'''
            print(value,'value的值是')
            if value != self.base:
            # if value != 1:
                message = '这个字段必须是%s'%self.base
                raise serializers.ValidationError(message)   # 这里抛出来的错误,就会被ser.errors接收,展示给用户
    
    
    # 第一种:如果是自己定义的序列化的类(与下边的验证类二选一)
    class UserSerializer(serializers.Serializer):
        name = serializers.CharField(min_length=5)
        pwd = serializers.CharField(error_messages={'required':'密码不能为空'},validators=[PassworValidator('666'),])  # 这里的666是验证规则,也可以不写,直接在上边类的__call__方法中写
    
    # 第二种:直接继承自modelSerializer类的序列化类 (与上边的验证类二选一)
    class UserSerialazer(serializers.ModelSerializer):
        class Meta:
            model = models.UserInfo
            fields = "__all__"
    
            # 定义字段的验证规则
            extra_kwargs = {
                'name':{'min_length':3},
                'pwd':{'validator':[PassworValidator('666')],}  # PassworValidator中,可以传参数,也可以不传参数。
            }
    
    class UserView(APIView):
    
        def get(self,request,*args,**kwargs):
            user_list = models.UserInfo.objects.all()
            ser = UserSerializer(instance=user_list,many=True)
            print(ser.data)
            return Response(ser.data)
    
        def post(self,request,*args,**kwargs):
            ser = UserSerializer(data=request.data)   # 生成一个对象
            if ser.is_valid():
                ret = ser.data          # ser.data是ReturnDict类型,这个类型继承自OrderedDict,OrderedDict继承自dict
                ret = ser.validated_data         # ser.data是ReturnDict类型,这个类型继承自OrderedDict,OrderedDict继承自dict
            else:
                print(ser.errors)
                print(ser.error_messages)
            return Response('POST 请求,相应内容')
  • 相关阅读:
    CF 120F Spider 树的直径 简单题
    POJ 1155 TELE 背包型树形DP 经典题
    CF 219D Choosing Capital for Treeland 树形DP 好题
    POJ 3162 Walking Race 树形DP+线段树
    HDU 2196 Computer 树形DP 经典题
    __str__()、__repr__()和__format__()
    item系列方法
    getattribute
    isinstance和issubclass
    继承方式完成包装
  • 原文地址:https://www.cnblogs.com/fengqing89/p/8490201.html
Copyright © 2011-2022 走看看