20-Django REST framework-Serializer序列化器

简介: 20-Django REST framework-Serializer序列化器

前言

  • 本篇来学习Serializer序列化器知识

序列化器作用

  • 进行数据的校验
  • 对数据对象进行转换

定义Serializer

定义方法

  • 模型
# models.py
from django.db import models
# Create your models here.
# 准备书籍列表信息的模型类
class BookInfo(models.Model):
    # 创建字段,字段类型
    name = models.CharField(max_length=20, verbose_name='名称')  # verbose_name admin管理后台使用
    pub_date = models.DateField(verbose_name='发布日期', null=True)
    readcount = models.IntegerField(default=0, verbose_name='阅读量')
    commentcount = models.IntegerField(default=0, verbose_name='评论量')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    class Meta:
        db_table = 'bookinfo'  # 指明数据库表名
        verbose_name = '图书'  # 在admin站点中显示的名称
    def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.name
  • 序列化器
# -*- coding: utf-8 -*-
# @Time    : 2022/9/24
# @Author  : 大海
# serializers.py
from rest_framework import serializers
from book.models import BookInfo
class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    name = serializers.CharField(max_length=20, label='名称')  # label DRF接口页面展示使用
    pub_date = serializers.DateField(label='发布日期', required=True)
    readcount = serializers.IntegerField(required=False, label='阅读量')
    commentcount = serializers.IntegerField(required=False, label='评论量')
    is_delete = serializers.BooleanField(required=False, label='逻辑删除')

字段与选项

  • 常用字段类型
  • 选项参数
参数名称 作用
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最小值
min_value 最大值
  • 通用参数
参数名称 说明
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息

创建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属性获取。

序列化使用

基本使用

  • 进入Django shell模式
python manage.py shell
  1. 查询一个图书对象
from book.models import BookInfo
book = BookInfo.objects.get(id=1)
  1. 构造序列化器
from book.serializers import BookInfoSerializer
serializer = BookInfoSerializer(book)
  1. 获取序列化数据
serializer.data
  1. 如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books,many=True)
serializer.data

增加额外字段

# serializers.py
from rest_framework import serializers
class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    name = serializers.CharField(max_length=20, label='名称')  # label DRF接口页面展示使用
    pub_date = serializers.DateField(label='发布日期', required=True)
    readcount = serializers.IntegerField(required=False, label='阅读量')
    commentcount = serializers.IntegerField(required=False, label='评论量')
    is_delete = serializers.BooleanField(required=False, label='逻辑删除')
    hello = serializers.CharField()  # 增加模型中不存在字段
  • 进入Django shell模式
python manage.py shell
from book.models import BookInfo
book = BookInfo.objects.get(id=1)
book.hello = '666'
from book.serializers import BookInfoSerializer
serializer = BookInfoSerializer(book)
serializer.data

关联对象序列化

  • models.py
from django.db import models
# Create your models here.
# 准备书籍列表信息的模型类
class BookInfo(models.Model):
    # 创建字段,字段类型
    name = models.CharField(max_length=20, verbose_name='名称')  # verbose_name admin管理后台使用
    pub_date = models.DateField(verbose_name='发布日期', null=True)
    readcount = models.IntegerField(default=0, verbose_name='阅读量')
    commentcount = models.IntegerField(default=0, verbose_name='评论量')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    class Meta:
        db_table = 'bookinfo'  # 指明数据库表名
        verbose_name = '图书'  # 在admin站点中显示的名称
  def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.name
# 准备人物列表信息的模型类
class PeopleInfo(models.Model):
    # 定义一个有序字典
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    name = models.CharField(max_length=20, verbose_name='名称')
    gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
    description = models.CharField(max_length=200, null=True, verbose_name='描述信息')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    # 外键 ForeignKey
    # 系统会字典为外加添加  id
    # 外键的级联操作  1对多 (书籍对人物)
    # CASCADE:删除主表数据时连通一起删除外键表中数据
    book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')
    class Meta:
        db_table = 'peopleinfo'
        verbose_name = '人物信息'
  • serializers.py
# -*- coding: utf-8 -*-
# @Time    : 2022/9/24
# @Author  : 大海
from abc import ABC
from rest_framework import serializers
from book.models import BookInfo
class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    name = serializers.CharField(max_length=20, label='名称')  # label DRF接口页面展示使用
    pub_date = serializers.DateField(label='发布日期', required=True)
    readcount = serializers.IntegerField(required=False, label='阅读量')
    commentcount = serializers.IntegerField(required=False, label='评论量')
    is_delete = serializers.BooleanField(required=False, label='逻辑删除')
    # hello = serializers.CharField()  # 增加模型中不存在字段
class HeroInfoSerializer(serializers.Serializer):
    """英雄数据序列化器"""
    GENDER_CHOICES = (
        (0, 'female'),
        (1, 'male')
    )
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='名字', max_length=20)
    gender = serializers.ChoiceField(choices=GENDER_CHOICES, label='性别', required=False)
    description = serializers.CharField(label='描述信息', max_length=200, required=False, allow_null=True)
    is_delete = serializers.BooleanField(label='是否删除', required=False)
    # 默认序列化外键id
    # book = serializers.PrimaryKeyRelatedField(label='书籍', read_only=True)
    # 序列化关联模型的__str__方法返回值序列化
    # book = serializers.StringRelatedField(label='书籍', read_only=True)
    # 关联模型序列化器所有字段序列化
    book = BookInfoSerializer()
    # book = serializers.PrimaryKeyRelatedField(label='书籍', queryset=BookInfo.objects.all())
#  book = serializers.PrimaryKeyRelatedField(label='书籍', read_only=True) 默认序列化外键id
In [1]: from book.models import BookInfo,PeopleInfo
In [2]: from book.serializers import BookInfoSerializer,HeroInfoSerializer
In [3]: hero = PeopleInfo.objects.get(id=1)
In [4]: serializer = HeroInfoSerializer(instance=hero)
In [5]: serializer.data
Out[5]: {'id': 1, 'name': '郭靖', 'gender': 1, 'description': '降龙十八掌', 'is_delete': False, 'book': 1}
# book = serializers.StringRelatedField(label='书籍', read_only=True) 序列化关联模型的__str__方法返回值序列化
In [1]: from book.serializers import BookInfoSerializer,HeroInfoSerializer
   ...: 
   ...: from book.models import BookInfo,PeopleInfo
   ...: 
   ...: hero = PeopleInfo.objects.get(id=1)
   ...: 
   ...: serializer = HeroInfoSerializer(instance=hero)
In [2]: serializer.data
Out[2]: {'id': 1, 'name': '郭靖', 'gender': 1, 'description': '降龙十八掌', 'is_delete': False, 'book': '射雕英雄传'}
# book = BookInfoSerializer()
In [1]: from book.serializers import BookInfoSerializer,HeroInfoSerializer
   ...: 
   ...: from book.models import BookInfo,PeopleInfo
   ...: 
   ...: hero = PeopleInfo.objects.get(id=1)
   ...: 
   ...: serializer = HeroInfoSerializer(instance=hero)
In [2]: serializer.data 关联模型序列化器所有字段序列化
Out[2]: {'id': 1, 'name': '郭靖', 'gender': 1, 'description': '降龙十八掌', 'is_delete': False, 'book': OrderedDict([('nam
e', '射雕英雄传'), ('pub_date', '1980-05-01'), ('readcount', 12), ('commentcount', 34), ('is_delete', False)])}

反序列使用

  • 进入Django shell模式
: data = {
   ...:     'name': '北漂纪实',
   ...:     'pub_date':'2022-12-10'
   ...: }
In [2]: from book.serializers import BookInfoSerializer
In [3]: serializer = BookInfoSerializer(data=data)
In [4]: serializer.is_valid(raise_exception=True)  # 调用序列化器校验方法
Out[4]: True
In [5]: serializer.errors   # 获取错误信息
Out[5]: {}
In [6]: serializer.validated_data  # 获取反序列化后的数据
Out[6]: OrderedDict([('name', '北漂纪实'), ('pub_date', datetime.date(2022, 12, 10))])
  • 单个字段校验
class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    name = serializers.CharField(max_length=20, label='名称')  # label DRF接口页面展示使用
    pub_date = serializers.DateField(label='发布日期', required=True)
    readcount = serializers.IntegerField(required=False, label='阅读量')
    commentcount = serializers.IntegerField(required=False, label='评论量')
    is_delete = serializers.BooleanField(required=False, label='逻辑删除')
    # hello = serializers.CharField()  # 增加模型中不存在字段
    peopleinfo_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)  # 序列化id
    # peopleinfo_set = HeroInfoSerializer(many=True)  # 一关联多 需要指定many=true 全部值
    def validate_name(self, value):
        """序列化器中单个字段校验"""
        if 'django' not in value.lower():
            raise serializers.ValidationError("图书不是关于Django的")
        return value
  • shell 模式
from book.serializers import BookInfoSerializer
In [2]: data = {
   ...:     'name': '北漂纪实',
   ...:     'pub_date':'2022-12-10'
   ...: }
In [3]: serializer = BookInfoSerializer(data=data)
serializer.is_valid(raise_exception=True)
   ...: 
   ...: 
---------------------------------------------------------------------------
ValidationError                           Traceback (most recent call last)
<ipython-input-5-c24be91bdde3> in <module>
----> 1 serializer.is_valid(raise_exception=True)
      2
D:\Python39\lib\site-packages\rest_framework\serializers.py in is_valid(self, raise_exception)
    233
    234         if self._errors and raise_exception:
--> 235             raise ValidationError(self.errors)
    236
    237         return not bool(self._errors)
ValidationError: {'name': [ErrorDetail(string='图书不是关于Django的', code='invalid')]}
  • serializers.py
class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    name = serializers.CharField(max_length=20, label='名称')  # label DRF接口页面展示使用
    pub_date = serializers.DateField(label='发布日期', required=True)
    readcount = serializers.IntegerField(required=False, label='阅读量')
    commentcount = serializers.IntegerField(required=False, label='评论量')
    is_delete = serializers.BooleanField(required=False, label='逻辑删除')
    # hello = serializers.CharField()  # 增加模型中不存在字段
    peopleinfo_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)  # 序列化id
    # peopleinfo_set = HeroInfoSerializer(many=True)  # 一关联多 需要指定many=true 全部值
    def validate_name(self, value):
        """序列化器中单个字段校验
        validate_<field_name>
        """
        if 'django' not in value.lower():
            raise serializers.ValidationError("图书不是关于Django的")
        return value
    def validate(self, attrs):
        """多个字段校验
        attrs 传过来的数据 字典类型
        """
        bread = attrs['readcount']
        bcomment = attrs['commentcount']
        if bread < bcomment:
            raise serializers.ValidationError('阅读量小于评论量')
        return attrs
    def create(self, validated_data):
        """新建"""
        return BookInfo.objects.create(**validated_data)
    def update(self, instance, validated_data):
        """更新,instance为要更新的对象实例"""
        instance.name = validated_data.get('name', instance.name)
        instance.readcount = validated_data.get('readcount', instance.readcount)
        instance.commentcount = validated_data.get('commentcount', instance.commentcount)
        instance.save()
        return instance
  • 修改
from book.serializers import BookInfoSerializer
In [4]: from book.models import BookInfo
In [5]: book = BookInfo.objects.get(id=5)
In [6]: data = {
   ...:     'name': '北漂纪实007-django',
   ...:     'pub_date':'2022-12-10',
   ...:     'readcount': 20,
   ...:     'commentcount':10
   ...: }
In [7]: serializer = BookInfoSerializer(book,data)
In [8]: serializer.is_valid(raise_exception=True)
Out[8]: True
In [9]: serializer.save()
Out[9]: <BookInfo: 北漂纪实007-django>

模型类序列化器ModelSerializer

  • 模型序列化器
from rest_framework import serializers
from book.models import BookInfo
class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo  # 指定模型
        fields = '__all__'  # 指定序列化器包含所有字段

指定字段

  1. 使用fields来明确字段,__all__表名包含所有字段,也可以写明具体哪些字段,如
class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        fields = ['id', 'name', 'bpub_date']
  1. 使用exclude可以明确排除掉哪些字段
class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        exclude = ['readcount']
  1. 指明只读字段
class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
        read_only_fields = ('id', 'readcount')
  1. 修改选项参数
lass BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
        extra_kwargs = {
            'readcount': {'min_value': 0, 'required': True},
            'commentcount': {'min_value': 0, 'required': True},
        }


相关文章
|
10天前
|
存储 数据安全/隐私保护 网络架构
DRF Django REST framework 之 认证组件(五)
DRF Django REST framework 之 认证组件(五)
|
11天前
|
存储 JSON 数据库
Django REST framework关联序列化器详解:掌握复杂关系的序列化与反序列化艺术
Django REST framework关联序列化器详解:掌握复杂关系的序列化与反序列化艺术
|
11天前
|
JSON API 数据格式
Django REST framework序列化器详解:普通序列化器与模型序列化器的选择与运用
Django REST framework序列化器详解:普通序列化器与模型序列化器的选择与运用
|
11天前
|
安全 API 数据安全/隐私保护
Django REST framework安全实践:轻松实现认证、权限与限流功能
Django REST framework安全实践:轻松实现认证、权限与限流功能
|
11天前
|
JSON 前端开发 API
Django API开发实战:前后端分离、Restful风格与DRF序列化器详解
Django API开发实战:前后端分离、Restful风格与DRF序列化器详解
|
11天前
|
JSON 搜索推荐 数据库
Django REST framework数据展示技巧:分页、过滤与搜索的实用配置与实践
Django REST framework数据展示技巧:分页、过滤与搜索的实用配置与实践
|
11天前
|
JSON API 网络架构
Django REST framework视图集与路由详解:深入理解ViewSet、ModelViewSet与路由映射器
Django REST framework视图集与路由详解:深入理解ViewSet、ModelViewSet与路由映射器
|
11天前
|
前端开发 数据管理 API
Django REST framework中GenericAPIView与混入扩展类详解
Django REST framework中GenericAPIView与混入扩展类详解
|
22天前
|
JSON 前端开发 API
Django进阶:DRF(Django REST framework)
Django进阶:DRF(Django REST framework)
|
2月前
|
缓存 API 数据库
Django中的REST框架
【5月更文挑战第20天】Django的REST框架使得在Python中构建和管理API变得简单。本文详细介绍了如何使用Django REST框架,从安装库到创建简单的用户API,包括模型、序列化器、视图集和路由配置。此外,还讨论了REST原则、认证、权限控制、响应格式定制、分页过滤、数据验证、错误处理、测试、文档、异步视图、性能优化、安全性、版本控制、迁移、数据序列化、文件上传、身份验证、授权、响应定制、错误处理、性能监控、缓存和测试。Django REST框架为高效API开发提供了全面支持。
32 3