• 快速上手Django(六) -Django之Django drf 序列化器Serializer类


    快速上手Django(六) -Django之Django drf 序列化器Serializer类

    1. 背景

    在Django中,前端传来的数据,一般是JSON格式的数据,获取数据需要通过request.POST.get('xxx)的形式拿到数据,对数据操作完后,返回给前端,也需要转成JSON格式,比较麻烦。

    不使用 Serializer 序列化会比较繁琐。drf中提供了序列化器的功能,解决了这一过程。过程:通过ORM从数据库获取数据对象–>调用序列化器,序列化数据–>将序列化的数据返回给前端.

    功能
      序列化:把模型对象转为字典,经过response后转成JSON字符串
      反序列化:把客户端传来的数据,经过request后转为字典。并完成数据校验功能。序列化器可以把字典转为模型对象。

    2. 使用思路

    Django DRF 序列化类
    参考URL: https://blog.csdn.net/m0_58987515/article/details/125285865

    序列化中有2种序列化,一种为 serializers.Serializer 。另一种在 第一个基础下 再次封装 serializers.ModelSerializer

    1. 在应用下新建任意名字文件例如 serializer.py 文件
    2. 定义一个Serializer类型的序列化器继承 serializers.Serializer 类 或 serializers.ModelSerializer 类。
    Serializer 的构造方法为:
    Serializer(instance=None, data=empty, **kwarg)
    
    • 1
    • 2

    1)用于序列化时,将模型类对象传入instance参数
    2)用于反序列化时,将要被反序列化的数据传入data参数
    3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据例如
    serializer = AccountSerializer(account, context={‘request’: request})

    注意点:

    • 使用序列化器的时候需要注意,声明序列化器后,不会自动执行,需要在视图中调用才可以。
    • 序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时把使用的数据传递过来。
    • 序列化器的字段声明类似于表单系统。
    • 开发 restful api 时,序列化器会帮我们把模型数据转换成字典.
    • drf 提供的视图会帮我们把字典转换成 json,或者把客户端发送过来的数据转换字典.

    3. 代码demo

    from rest_framework.views import APIView
    from api import models
    from api import ser
    from rest_framework.response import Response
    
    
    class BoosView(APIView):
        def get(self,request,pk):
            # 根据pk拿数据
            book_queryset = models.Books.objects.filter(id=pk).first()
            # 调用序列化组件,序列化数据
            book_ser = ser.BookSerializer(book_queryset)
            # 序列化对象.data就是序列化后的字典
            return Response(book_ser.data)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如果接收一个列表,那么应该将many=True标志传递给嵌套的序列化器。

    class Web3UrlViewSet(ModelViewSet):
        queryset = Web3UrlModel.objects.all()
    
        # 返回常用url
        def list(self, request, *args, **kwargs):
            queryset = Web3UrlModel.objects.get_queryset().order_by("-id")
    
            serializer = Web3UrlSerializer(queryset, many=True)
            # MyJsonResponse {'code': code, 'msg': msg, 'data': data}
            return MyJsonResponse(data=serializer.data)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4. 【重要】序列化类 ModelSerializer

    官网:https://www.django-rest-framework.org/api-guide/serializers/

    工作中会发现大部分的序列化都与我们的模型紧密相关。

    如果使用序列化器对应 Django 的模型类,DRF为我们提供了 ModelSerializer 模型类序列化器来帮助我们快速创建一个 Serializer 类。 它会根据模型自动生成一组字段;它简单的默认实现了.update()以及.create()方法。总体来说 serializers.ModelSerializer 还是比较好用,写起来方便很多。

    ModelSerializer 与常规的 Serializer 相同,但提供了:

    • 基于模型类自动生成一系列字段
    • 基于模型类自动为 Serializer 生成 validators,比如 unique_together
    • 包含默认的 create() 和 update() 的实现
    from rest_framework import serializers
    from .models import MyBook
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = MyBook
            fields = '__all__'
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 该序列化类需要继承 serializers.ModelSerializer
    • model 指明参照哪个模型类,例如示例中的指定的模型表,可以理解为将模型表中的字段映射成类似于 title = serializers.CharField(max_length=32)
    • fields 指明为模型类的哪些字段生成,'all’用于表示全部字段,也可以指定字段:fields = [‘title’, ‘price’]。还可以排除字段: exclude [‘title’]

    ModelSerializer类,它为创建用于处理模型实例和查询集的序列化程序提供了有用的快捷实现方式。

    5. DRF序列化器to_representation()和to_internal_value()方法

    DRF所有序列化器类都继承了BaseSerializer 类, 通过重写该类的 to_representation() 和**to_internal_value()**方法可以改变序列化和反序列化的行为,比如给序列化后的数据添加额外的数据,或者对客户端API请求携带的数据进行反序列化处理以及用来自定义序列化器字段。

    • to_representation() 允许我们改变序列化的输出。
    • to_internal_value() 允许改变我们反序列化的输出。

    重写 to_representation() 和to_internal_value()方法不仅可以改变序列化数据的输出,处理反序列化的输入数据,还可以用来自定义字段。

    to_representation() 和to_internal_value()方法的另一个重要用途就是用来自定义序列化类字段。下例为DRF提供的一个官方演示,展示了如何使用这两个方法自定义了一个包含有x, y坐标的字段CoordinateField字段。

    # 自定义字段
    class CoordinateField(serializers.Field):
     
     
        def to_representation(self, value):
            ret = {
                "x": value.x_coordinate,
                "y": value.y_coordinate
            }
            return ret
     
     
        def to_internal_value(self, data):
            ret = {
                "x_coordinate": data["x"],
                "y_coordinate": data["y"],
            }
            return ret
     
     
    # 定义好后,可以在序列化类中使用。
    class DataPointSerializer(serializers.ModelSerializer):
        coordinates = CoordinateField(source='*')
     
     
        class Meta:
            model = DataPoint
            fields = ['label', 'coordinates']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    to_representation如何使用

    在视图类中,我们指定序列化器类

    class UserViewSet(ModelViewSet):
        queryset = User.objects.filter()
        serializer_class = UserSerializer
    
    • 1
    • 2
    • 3

    然后我们自定义序列化器类,我们覆写to_representation

    class UserSerializer(serializers.ModelSerializer):
        
        def to_representation(self, instance):
        		...
    
    • 1
    • 2
    • 3
    • 4

    示例:例如处理返回的日期格式

    class ProductsSerializer(serializers.ModelSerializer):
        # 项目数据序列化器
    
        class Meta:
            model = Products
            fields = '__all__'  # 返回所有字段
    
        def to_representation(self, instance):
            data = super().to_representation(instance)
            # data['create_time']获取到数据库里存储的时间戳,然后用localtime()函数转换为localtime
            time_local = time.localtime(data['create_time'])
            # 拿到转换后的time_local再用strftime()函数重新格式化时间
            data['create_time'] = time.strftime("%Y-%m-%d %H:%M:%S", time_local)
            # 返回处理之后的数据
            return data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    处理之后返回的数据:在这里插入图片描述
    在这里插入图片描述

    6. 工作常用使用总结

    drf Serializer 只返回特定字段(ModelSerializer只序列化特定字段)

    ModelSerializer指定序列化字段三种方法:

    class CategorySerializer(serializers.ModelSerializer):
        class Meta:
            model = Category
            # 1.序列化指定字段
            fields = ('id', 'name',)
            # 2.序列化全部所有的字段
            fields = '__all__'
            # 3. 序列化除了user以外的所有字段
            exclude = ('user',)
    '''
    三种方法只能使用一种
    第二种和第三种方法有暴露数据的风险
    例如数据库有password字段,第二种会直接序列化出来,第三种,如果没有排除的话,也会序列化出来
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    经过测试, fields = 定义的顺序,也是json返回的字段的顺序。

    参考

    重写DRF的to_representation和to_internal_value方法有什么用途?
    参考URL: https://blog.csdn.net/weixin_42134789/article/details/115191672
    Django DRF 序列化类
    参考URL: https://blog.csdn.net/m0_58987515/article/details/125285865

  • 相关阅读:
    Nuxt3第二篇【路由】
    服务器相关概念1
    如何读取maven依赖的jar包中的代码?
    OTA设计思路
    【对象存储】Minio本地运行和 golang客户端基本操作
    遍历用for还是foreach?
    请问一下出现这种错误怎么解决呢(标签-xml)
    【全开源】JAVA打车小程序APP打车顺风车滴滴车跑腿源码微信小程序打车源码
    javaweb登录注册页面页面的完整代码
    Java性能优化可算是讲明白了,优化权威指南就是强
  • 原文地址:https://blog.csdn.net/inthat/article/details/128188398