如何使用DRF的序列化器之序列化

DRF两大利器为Serizlizer序列化器和视图,而序列化器又分为序列化和反序列化,本篇文章首先来看下DRF序列化器的常用序列化方法。

首先来看使用Django开发REST接口时的表现,示例代码如下:

# views.py

from datetime import datetime

class BooksAPIVIew(View):
    """
    查询所有图书、增加图书
    """
    def get(self, request):
        """
        查询所有图书
        路由:GET /books/
        """
        queryset = BookInfo.objects.all()
        book_list = []
        # 将BookInfo对象转换为字典
        for book in queryset:
            book_list.append({
                'id': book.id,
                'btitle': book.btitle,
                'bpub_date': book.bpub_date,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'image': book.image.url if book.image else ''
            })
        # book_list为包含很多字典的列表
        return JsonResponse(book_list, safe=False)

    def post(self, request):
        """
        新增图书
        路由:POST /books/ 
        """
        json_bytes = request.body
        json_str = json_bytes.decode()
        book_dict = json.loads(json_str)

        # 此处详细的校验参数省略

        book = BookInfo.objects.create(
            btitle=book_dict.get('btitle'),
            bpub_date=datetime.strptime(book_dict.get('bpub_date'), '%Y-%m-%d').date()
        )

        return JsonResponse({
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
            'image': book.image.url if book.image else ''
        }, status=201)

当我们得到Queryset时或者得到一个BookInfo对象时,需要将BookInfo对象转换为字典,将包含字典类型数据的列表转换为json数据响应回去。其中将BookInfo对象转换为字典的代码冗余的厉害,此时serializer就可以大显身手了。

使用序列化器首先需要在serializers.py中定义序列化器类:

字段名称和模型类中的字段名相同,字段的选项约束有很多,默认约束required为True!

详细可以参看官方文档:https://www.django-rest-framework.org/

Github源码:https://github.com/encode/django-rest-framework/tree/master

# 需要继承DRF的serilalizers中的Serializer
from rest_framework import serializers
from .models import BookInfo
class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    btitle = serializers.CharField(
        min_length=3,
        max_length=10,
        error_messages={
            'min_length': '书名要大于3个字符',
            'max_length': '书名要小于10个字符'
        }
    )
    bpub_date = serializers.DateField()
    bread = serializers.IntegerField()
    bcomment = serializers.IntegerField(label='评论量', required=False)

创建Serializer对象

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

Serializer的构造方法为:

Serializer(instance=None, data=empty, **kwarg)

说明:

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

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

3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如

serializer = AccountSerializer(account, context={'request': request})

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

掌握了上述知识后我们就可以开始进行序列化操作了

class Book2View(View):
    def get(self, request):

        # 序列化列表
        blist = BookInfo.objects.all()
        # 1.创建序列化对象,如果被序列化的是包含多条数据的查询集QuerySet
        # 需要添加many=True参数补充说明
        # 以列表为参数,列表中是模型类对象
        serializer = serializers.BookSerializer(blist, many=True)
        # 2.调用属性data,通过data属性可以获取序列化后的数据
        # 获取转换后的列表,列表中是有序字典对象
        """
        [OrderedDict([('id', 2), ('btitle', '天龙八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bcomment', 40)]), OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80)])]
        """
        book_dict_list = serializer.data
        # 响应
        return JsonResponse(book_dict_list, safe=False)
        

关联对象嵌套序列化

如果需要序列化的数据中包含有其他关联对象,则对关联对象数据的序列化需要指明。注:书籍与英雄的关系为一对多

在定义序列化器类的代码中添加如下代码,注意在定义关联属性时,必须添加约束read_only = True

# 关系属性输出的3种方案
    # 1.主键 此字段将被序列化为关联对象的主键。
    # heros = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
    # 2.字符串
    # heros = serializers.StringRelatedField(read_only=True, many=True)
    # 3.自定义序列化器
    heros = HeroSerializer(read_only=True, many=True)

如果关联的对象数据不是只有一个,而是包含多个数据,如想序列化图书BookInfo数据,每个BookInfo对象关联的英雄HeroInfo对象可能有多个,则在约束中添加many=True参数即可。

 PrimaryKeyRelatedField: 此字段将被序列化为关联对象的主键

StringRelatedField:此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)(定义模型类时添加__str__方法)

HeroSerializer:使用关联对象的序列化器,需要自己定义关联对象的序列化器

序列化器的序列化方法帮助我们封装了将python类型(模型类对象、模型类对象的列表)转换为字典的过程,加快开发效率。

# 将模型类对象转换成字典的过程
serializer = serializers.HeroSerializer(hero)
hero_dict = serializer.data
# 将模型类对象的列表转换为字典列表
serializer = serializers.BookSerializer(blist, many=True)
book_dict_list = serializer.data

猜你喜欢

转载自blog.csdn.net/w18306890492/article/details/84728608