20-Django REST framework-Serializer序列化器
Posted 爱学习de测试小白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20-Django REST framework-Serializer序列化器相关的知识,希望对你有一定的参考价值。
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
- 查询一个图书对象
from book.models import BookInfo
book = BookInfo.objects.get(id=1)
- 构造序列化器
from book.serializers import BookInfoSerializer
serializer = BookInfoSerializer(book)
- 获取序列化数据
serializer.data
- 如果要被序列化的是包含多条数据的查询集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):
以上是关于20-Django REST framework-Serializer序列化器的主要内容,如果未能解决你的问题,请参考以下文章
Django-rest-framework 和 django-rest-framework-jwt APIViews and validation Authorization headers
Django Rest Framework 和 django Rest Framework simplejwt 两因素身份验证