rest-framework序列化

一、创建表及手动插入数据,以便后面操作

  • 1、创建用户组表

    class UserGroupModel(models.Model):
        """
        创建一个用户分组的
        """
        title = models.CharField(max_length=100, null=False, verbose_name='用户分组')
    
  • 2、创建用户角色表

    class RoleModel(models.Model):
        """
        创建一个角色表
        """
        title = models.CharField(max_length=100, null=False, blank=False, verbose_name='角色名称')
    
  • 3、创建用户表

    class UserModel(models.Model):
        """
        创建一个用户表
        """
        user_type_choices = (
            (1, '普通用户'),
            (2, 'VIP用户')
        )
        user_type = models.IntegerField(choices=user_type_choices, null=False, verbose_name='用户类型')
        # 外键关联到用户分组表
        group = models.ForeignKey('UserGroupModel', on_delete=models.CASCADE)
        # 用户表与角色表进行多对多的关联
        roles = models.ManyToManyField('RoleModel')
    
        username = models.CharField(max_length=100, null=False, verbose_name='用户名')
        password = models.CharField(max_length=100, null=False, verbose_name='密码')
    
  • 4、创建token

    class UserTokenModel(models.Model):
        """
        创建一个用户token表
        """
        user = models.OneToOneField(to='UserModel', on_delete=models.CASCADE)
        token = models.CharField(max_length=100, verbose_name='用户token')
    

二、不使用rest-framework序列化返回json数据

  • 1、返回的是字符

    from django.shortcuts import HttpResponse
    from django.http import JsonResponse
    from rest_framework.views import APIView
    import json
    
    from app01 import models
    
    class RoleView1(APIView):
        """
        使用原始的方式返回字符
        """
    
        def get(self, request, *args, **kwargs):
            role = models.RoleModel.objects.all().values('id', 'title')
            role = list(role)
            ret = json.dumps(role, ensure_ascii=False)
            return HttpResponse(ret)
    

三、官网这个地方分三个来章节来介绍

四、使用rest-framework序列化

  • 1、在app包下创建一个文件serializers.py
  • 2、导包

    from rest_framework import serializers
    
  • 3、新增一个序列化的类

    class RolesSerializer(serializers.Serializer):
        """
        序列化角色表
        """
        title = serializers.CharField()
    
  • 4、在视图类中使用序列化类

    class RoleView2(APIView):
        """
        使用rest-framework序列化返回数据
        """
    
        def get(self, request, *args, **kwargs):
            role = models.RoleModel.objects.all()
            # many=True表示返回多条数据(一般列表写many=True,对象就写many=False)
            ser = RolesSerializer(instance=role, many=True)
            # 直接使用序列化后的.data
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)
    
  • 5、返回对象

    from app01.serializer import RolesSerializer
    
    class RoleView2(APIView):
        """
        使用rest-framework序列化返回数据
        """
    
        def get(self, request, *args, **kwargs):
            role = models.RoleModel.objects.all().first()
            ser = RolesSerializer(instance=role, many=False)
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)
    
  • 6、总结:

    • 1、在项目开发过程中一般会把serializer与视图类分开不同文件来写,通过导包的方式导入
    • 2、serializer也可以做分发功能(文件明了)

五、序列化常见的字段

  • 1、源码中拷贝出来的

    serializer_field_mapping = {
        # 对应model中的字段:serializer对应的字段
        models.AutoField: IntegerField,
        models.BigIntegerField: IntegerField,
        models.BooleanField: BooleanField,
        models.CharField: CharField,
        models.CommaSeparatedIntegerField: CharField,
        models.DateField: DateField,
        models.DateTimeField: DateTimeField,
        models.DecimalField: DecimalField,
        models.EmailField: EmailField,
        models.Field: ModelField,
        models.FileField: FileField,
        models.FloatField: FloatField,
        models.ImageField: ImageField,
        models.IntegerField: IntegerField,
        models.NullBooleanField: NullBooleanField,
        models.PositiveIntegerField: IntegerField,
        models.PositiveSmallIntegerField: IntegerField,
        models.SlugField: SlugField,
        models.SmallIntegerField: IntegerField,
        models.TextField: CharField,
        models.TimeField: TimeField,
        models.URLField: URLField,
        models.GenericIPAddressField: IPAddressField,
        models.FilePathField: FilePathField,
    }
    

六、关于source的使用

将用于填充字段的属性的名称。可以是一个只接受 self 参数的方法,如 URLField(source='get_absolute_url'),或者使用点符号来遍历属性,如 EmailField(source='user.email')

  • 1、序列化用户表

    class UserSerializer(serializers.Serializer):
        id = serializers.IntegerField()
        user_type = serializers.CharField()
        username = serializers.CharField()
        password = serializers.CharField()
    
    class UserView1(APIView):
        def get(self, request, *args, **kwargs):
            user = models.UserModel.objects.all()
            ser = UserSerializer(instance=user, many=True)
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)
    
  • 2、返回结果

    [{"id": 1, "user_type": "1", "username": "hello", "password": "123"}, {"id": 2, "user_type": "2", "username": "word", "password": "123"}, {"id": 3, "user_type": "1", "username": "hehe", "password": "123"}]
    
  • 3、我们要把user_type显示出中文字出来

    class UserSerializer(serializers.Serializer):
        id = serializers.IntegerField()
        # 会调用row.user_type字段
        xx = serializers.CharField(source="user_type")
        # source会调用row.get_user_type_display()方法
        yy = serializers.CharField(source="get_user_type_display")
        username = serializers.CharField()
        password = serializers.CharField()
    
    class UserView1(APIView):
        def get(self, request, *args, **kwargs):
            user = models.UserModel.objects.all()
            ser = UserSerializer(instance=user, many=True)
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)
    
  • 4、返回数据

    [{"id": 1, "xx": "1", "yy": "普通用户", "username": "hello", "password": "123"}, {"id": 2, "xx": "2", "yy": "VIP用户", "username": "word", "password": "123"}, {"id": 3, "xx": "1", "yy": "普通用户", "username": "hehe", "password": "123"}]
    

七、显示外键的值

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    xx = serializers.CharField(source="user_type")
    yy = serializers.CharField(source="get_user_type_display")
    username = serializers.CharField()
    password = serializers.CharField()
    # 通过.的方式获取外键的值
    gp = serializers.CharField(source='group.title')


class UserView1(APIView):
    def get(self, request, *args, **kwargs):
        user = models.UserModel.objects.all()
        ser = UserSerializer(instance=user, many=True)
        ret = json.dumps(ser.data, ensure_ascii=False)
        return HttpResponse(ret)

八、多对多的字段显示

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    xx = serializers.CharField(source="user_type")
    yy = serializers.CharField(source="get_user_type_display")
    username = serializers.CharField()
    password = serializers.CharField()
    gp = serializers.CharField(source='group.title')

    # 使用自定义字段来显示role
    role = serializers.SerializerMethodField()

    def get_role(self, row):
        """
        定义一个函数来获取role(get_自定义字段名)
        :param row:
        :return:
        """
        # 根据row获取全部的角色
        role_all = row.roles.all()
        ret = []
        for item in role_all:
            ret.append({'id': item.id, 'title': item.title})
        return ret

九、使用ModelSerializer直接返回字段

  • 1、将数据库表中字段全部返回

    # 注意这个地方要继承serializers.ModelSerializer
    class UserSerializer(serializers.ModelSerializer):
        class Meta(object):
            model = models.UserModel
            # 使用__all__表示返回表中全部的字段
            fields = '__all__'
    
    class UserView1(APIView):
        def get(self, request, *args, **kwargs):
            user = models.UserModel.objects.all()
            ser = UserSerializer(instance=user, many=True)
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)
    
  • 2、返回部分字段

    class UserSerializer(serializers.ModelSerializer):
        class Meta(object):
            model = models.UserModel
            # fields = '__all__'
            # 定义要返回的字段
            fields = ['id', 'username', 'password', 'roles']
    
    class UserView1(APIView):
        def get(self, request, *args, **kwargs):
            user = models.UserModel.objects.all()
            ser = UserSerializer(instance=user, many=True)
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)
    
  • 3、结合上面自定义字段

    class UserSerializer(serializers.ModelSerializer):
        yy = serializers.CharField(source="get_user_type_display")
        gp = serializers.CharField(source='group.title')
    
        # 使用自定义字段来显示role
        role = serializers.SerializerMethodField()
    
        class Meta(object):
            model = models.UserModel
            fields = ['id', 'username', 'password', 'yy', 'gp', 'role']
    
        def get_role(self, row):
            """
            定义一个函数来获取role(get_自定义字段名)
            :param row:
            :return:
            """
            # 根据row获取全部的角色
            role_all = row.roles.all()
            ret = []
            for item in role_all:
                ret.append({'id': item.id, 'title': item.title})
            return ret
    
    class UserView1(APIView):
        def get(self, request, *args, **kwargs):
            user = models.UserModel.objects.all()
            ser = UserSerializer(instance=user, many=True)
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)
    

十、深度查找

在上面我们介绍了使用source或者使用自定义字段来显示关联表的数据,其实在项目中开发也可以使用深度查找,简化代码量

  • 1、演示代码

    class UserSerializer(serializers.ModelSerializer):
        class Meta(object):
            model = models.UserModel
            fields = '__all__'
            depth = 1
    
  • 2、关于深度查找的认识

    • 1.深度查找是查找关于一对多,多对多的关系中使用到,用来查找关于外键相关联起来的字段
    • 2.深入查找的建议是1-10层,每一层就表示一个关系表的约束

十一、序列化生成hypermedialink(url模式,常见图片地址)

  • 1、定义一个分组的视图类

    from django.shortcuts import HttpResponse
    from rest_framework.views import APIView
    from rest_framework import serializers
    import json
    
    from app01 import models
    
    class GroupSerializer(serializers.ModelSerializer):
        class Meta(object):
            model = models.UserGroupModel
            fields = '__all__'
    
    class GroupView(APIView):
        def get(self, request, *args, **kwargs):
            id = kwargs.get('id')
            obj = models.UserGroupModel.objects.filter(id=id).first()
            ser = GroupSerializer(instance=obj, many=False)
            res = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(res)
    
  • 2、定义分组的url地址

    urlpatterns = [
      path('group/<int:id>/', group.GroupView.as_view(), name="gp"),
    ]
    
  • 3、序列化用户表

    class UserSerializer1(serializers.ModelSerializer):
        # 注意这个地方的lookup_url_kwarg要和配置url地址处的相同
        group = serializers.HyperlinkedIdentityField(view_name='gp', lookup_field='group_id', lookup_url_kwarg='id')
    
        class Meta(object):
            model = models.UserModel
            fields = ['id', 'username', 'password', 'group', 'roles']
            depth = 1
    
    class UserView1(APIView):
        def get(self, request, *args, **kwargs):
            user = models.UserModel.objects.all()
            # 注意如果这个地方使用了hypermedialink就要写上context={'request': request}
            ser = UserSerializer1(instance=user, many=True, context={'request': request})
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)
    
  • 4、返回数据

    [
        {
            "id": 1,
            "username": "hello",
            "password": "123",
            "group": "http://127.0.0.1:9000/app01/api/v1/group/1/",
            "roles": [
                {
                    "id": 1,
                    "title": "员工"
                },
                {
                    "id": 2,
                    "title": "经理"
                }
            ]
        }
    ]
    

十二、验证用户输入数据(类似前面的form)

  • 1、定义序列化的

    class GroupSerializer1(serializers.Serializer):
        title = serializers.CharField(required=True, error_messages={'required': '必填字段'})
    
  • 2、在视图类中使用

    class GroupView(APIView):
        def get(self, request, *args, **kwargs):
            id = kwargs.get('id')
            obj = models.UserGroupModel.objects.filter(id=id).first()
            ser = GroupSerializer(instance=obj, many=False)
            res = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(res)
    
        def post(self, request, *args, **kwargs):
            # 配置就解析器才可以这样取值
            ser = GroupSerializer1(data=request.data)
            if ser.is_valid():
                print(ser.validated_data)
            else:
                print(ser.errors)
            return HttpResponse('提交数据')
    

十三、使用序列化的综合案例

  • 1、总要功能,在序列化中定义创建的函数,然后使用post方式创建数据
  • 2、序列化数据

    from rest_framework import serializers
    from app01 import models
    
    class RolesSerializer(serializers.Serializer):
        id = serializers.IntegerField(required=False)
        title = serializers.CharField(required=True, max_length=100)
    
        def create(self, validated_data):
            """
            创建新增数据的时候
            :param validated_data:
            :return:
            """
            return models.RoleModel.objects.create(**validated_data)
    
  • 3、在视图中定义

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status
    
    from app01 import models
    from app01.serializers import roles
    
    class RoleView(APIView):
        def get(self, request, *args, **kwargs):
            """
            定义获取数据的视图
            """
            roles_all = models.RoleModel.objects.all()
            ser = roles.RolesSerializer(instance=roles_all, many=True)
            return Response(ser.data)
    
        def post(self, request, *args, **kwargs):
            """
            定义创建数据的视图,如果校验成功就添加到数据库,否则就返回错误
            """
            serializer = roles.RolesSerializer(data=request.data)
    
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED)
    
  • 4、视图中定义

    from django.urls import path
    from app01.views import roles
    
    urlpatterns = [
        path('roles/', roles.RoleView.as_view())
    ]
    

十四、总结

  • 1、如果是一对多的关系表(外键关联)就要使用source
  • 2、如果是多对多的关系表就要使用SerializerMethodField

results matching ""

    No results matching ""