Django REST Framework(五)DRF Serializer

作用:

1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能

  • 定义序列化器

    • Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。

      接下来,为了方便演示序列化器的使用,我们先创建一个新的子应用sers

      python manage.py startapp sers
      from django.db import models
      
      
      # Create your models here.
      
      class Book(models.Model):
          title = models.CharField(max_length=32,verbose_name="书籍名称")
          price = models.IntegerField(verbose_name="价格")
          pub_date = models.DateField(verbose_name="出版日期")

      我们想为Book模型类提供一个序列化器,可以定义如下:

      from rest_framework import serializers
      
      class BookSerializer(serializers.Serializer):
          title = serializers.CharField()
          price = serializers.IntegerField()
          pub_date = serializers.DateField()

      注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。

  • 创建Serializer对象

    • 定义好Serializer类后,就可以创建Serializer对象了。

      Serializer的构造方法为:Serializer(instance=None, data=empty, **kwarg)

    • 说明:

      • 用于序列化时,将模型类对象传入instance参数

      • 用于反序列化时,将要被反序列化的数据传入data参数

      • 除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如 serializer = AccountSerializer(account, context={'request': request})

    • 通过context参数附加的数据,可以通过Serializer对象的context属性获取。

      • 使用序列化器的时候一定要注意,序列化器声明了以后,不会自动执行,需要我们在视图中进行调用才可以。

      • 序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时把使用的数据传递过来。

      • 序列化器的字段声明类似于我们前面使用过的表单系统。

      • 开发restful api时,序列化器会帮我们把模型数据转换成字典.

      • drf提供的视图会帮我们把字典转换成json,或者把客户端发送过来的数据转换字典.

  • 序列化器的使用

    • 序列化器的使用分两个阶段:

      • 处理客户端请求时,使用序列化器可以完成对数据的反序列化。

      • 处理服务器响应时,使用序列化器可以完成对数据的序列化。

    • 序列化

      • 基本序列化
        • 先查询出一个学生对象
          from sers.models import Book
          book = Book.objects.get(pk=1)

        • 构造序列化器对象
          from .serializers import BookSerializer
          bookSer = BookSerializer(instance=book)
        • 获取序列化数据,通过data属性可以获取序列化后的数据
        • 路由
          # urls.py
          path("sers/", include("sers.urls")),
          # sers.urls
          path('books/(\d+)', BookView.as_view()),
        • 视图
          from rest_framework.response import Response
          from rest_framework.views import APIView
          from .models import Book
          from .sers import BookSerializer
          
          class BookView(APIView):
          
              def get(self, request,id):
                  book = Book.objects.get(pk=id)
                  bs = BookSerializer(instance=book)
                  return Response(bs.data)
        • 如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明
          class BookView(APIView):
          
              def get(self, request):
                  # book = Book.objects.get(pk=1)
                  books = Book.objects.all()
                  bs = BookSerializer(instance=books, many=True)
                  return Response(bs.data)

  • 反序列化

    • 数据验证
      • 使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。

        在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。

        验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。

        验证成功,可以通过序列化器对象的validated_data属性获取数据。

        在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。

        通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证。

        from sers.sers import BookSerializer
        bs = BookSerializer(data={"title":"小王子","price":100})
        bs.is_valid()  # 必须先要is_valid,才会有bs.validated_data和bs.errors
        False
        bs.validated_data
        {}
        bs.errors
        {'pub_date': [ErrorDetail(string='This field is required.', code='required')]}

        is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。

      • validate_字段名,对<field_name>字段进行验证,如
        class BookSerializer(serializers.Serializer):
            title = serializers.CharField(max_length=32)
            price = serializers.IntegerField(required=True)
            pub_date = serializers.DateField(required=True)
        
            def validate_title(self, value):
                if 'django' not in value.lower():
                    raise serializers.ValidationError("图书不是关于Django的")
                return value
      • 测试

        from sers.sers import BookSerializer
        bs = BookSerializer(data={"title":"小王子","price":100})
        bs.is_valid()
        False
        bs.errors
        {'title': [ErrorDetail(string='图书不是关于Django的', code='invalid')], 'pub_date': [ErrorDetail(string='This field is required.', code='required')]}
      • validate,在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证,如
        
        class BookSerializer(serializers.Serializer):
            title = serializers.CharField(max_length=32)
            price = serializers.IntegerField(required=False)
            pub_date = serializers.DateField(required=False)
        
            bread = serializers.IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
            bcomment = serializers.IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
        
        
            def validate_title(self, value):
                if 'django' not in value.lower():
                    raise serializers.ValidationError("图书不是关于Django的")
                return value
        
            def validate(self, data):
                bread = data.get("bread")
                bcomment = data.get("bcomment")
                if bread < bcomment:
                    raise serializers.ValidationError('阅读量小于评论量')
                return data
        
      • 反序列化-保存数据,

        前面的验证数据成功后,我们可以使用序列化器来完成数据反序列化的过程.这个过程可以把数据转成模型类对象.

        可以通过实现create()和update()两个方法来实现。

        在反序列化数据的时候,就可以通过save()方法返回一个数据对象实例了,book = serializer.save()
    • 基于APIView的接口实现

      • 路由
        urlpatterns = [
            path('book/', views.BookView.as_view()),
            re_path('book/(\d+)', views.BookDetailView.as_view()),
        ]
      • 视图
        # Create your views here.
        from rest_framework.views import APIView
        
        # 设计增删改查查接口
        
        
        # 视图
        class BookView(APIView):
        
            def get(self, request):
                books = Book.objects.all()
                bs = BookSerializer(instance=books, many=True)
                return Response(bs.data)
        
            def post(self, request):
                bs = BookSerializer(data=request.data)
                if bs.is_valid():
                    bs.save()
                    return Response(bs.data)
                else:
                    return Response(bs.errors)
        
        
        class BookDetailView(APIView):
        
            def get(self, request, pk):
                book = Book.objects.get(pk=pk)
                bs = BookSerializer(instance=book)
                return Response(bs.data)
        
            def put(self, request, pk):
                instance = Book.objects.get(pk=pk)
                bs = BookSerializer(instance=instance, data=request.data)
                if bs.is_valid():
                    bs.save()
                    return Response(bs.data)
                else:
                    return Response(bs.errors)
        
            def delete(self, request, pk):
                Book.objects.get(pk=pk).delete()
                return Response()
      • serializer
        # 序列化器
        from rest_framework import serializers
        from rest_framework.response import Response
        from .models import Book
        
        
        class BookSerializer(serializers.Serializer):
            title = serializers.CharField()
            price = serializers.IntegerField()
            pub_date = serializers.DateField()
        
            def create(self, validated_data):
                new_book = Book.objects.create(**validated_data)
        
                return new_book
        
            def update(self, instance, validated_data):
                Book.objects.filter(pk=instance.pk).update(**validated_data)
                instance = Book.objects.get(pk=instance.pk)
        
                return instance
        
        

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yjjpp2301

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值