赞
踩
使用Django前后端分离开发的情况下,我们经常需要把处理后的数据按照一定的格式(比如说json)返回,或者把前端传过来的数据进行处理才能进行数据库的CURD。而DRF(Django REST Framework)就可以帮忙我解决这个问题,即序列化和反序列化
使用pip安装
pip install djangorestframework
配置应用
INSTALLED_APPS = [
...
'rest_framework',
]
我们新建一个py文件专门写序列化类继承serializers.Serializer,写的字段和约束要在模型类范围之内
models.py
from django.db import models
class BookInfo(models.Model):
btitle = models.CharField(max_length=20, verbose_name='名称')
bpub_date = models.DateField(verbose_name='发布日期', null=True)
bread = models.IntegerField(default=0, verbose_name='阅读量')
bcomment = models.IntegerField(default=0, verbose_name='评论量')
image = models.ImageField(upload_to='booktest', verbose_name='图片', null=True)
serializers.py
from rest_framework import serializers
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
btitle = serializers.CharField(label='名称', max_length=20)
bpub_date = serializers.DateField(label='发布日期', required=False)
bread = serializers.IntegerField(label='阅读量', required=False)
bcomment = serializers.IntegerField(label='评论量', required=False)
image = serializers.ImageField(label='图片', required=False)
说明:Serializer的字段类型几乎与Models的一样,记不起来时直接查看serializers类即可
选项参数 | 说明 |
---|---|
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(instance=None, data=empty, **kwarg)
说明:
序列化单个对象
from booktest.models import BookInfo # 导入图书模型类
from booktest.serializers import BookInfoSerializer # 导入序列器类
book = BookInfo.objects.get(id=2) # 获取一个单一模型类对象
serializer = BookInfoSerializer(book) # 序列化单一模型类对象
serializer.data # 查看序列化之后的数据
序列化查询集
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True) # 要指定many=True
serializer.data # 查看结果
如果存在外键,在序列化的时候可能是序列化主表或从表两大方向
models.py
class BookInfo(models.Model):
...
def __str__(self):
return self.btitle
class HeroInfo(models.Model):
...
hbook = models.ForeignKey(BookInfo, related_name='heros',on_delete=models.CASCADE, verbose_name='图书') # 外键
def __str__(self):
return self.hname
serializers.py
class HeroInfoSerializer(serializers.Serializer): id = serializers.IntegerField() hname = serializers.CharField() hgender = serializers.IntegerField() hcomment = serializers.CharField() is_delete = serializers.BooleanField() class BookInfoSerializer(serializers.Serializer): id = serializers.IntegerField() btitle = serializers.CharField() bpub_date = serializers.DateField() bread = serializers.IntegerField() bcomment = serializers.IntegerField() is_delete = serializers.BooleanField() image = serializers.ImageField() 序列化主表BookInfo的时候,它的属性heros是关联的从表的多个对象 关联对象序列化方案一:序列化成关联对象的主键 heros = serializers.PrimaryKeyRelatedField( queryset=HeroInfo.objects.all(), many=True # 表示当前字段heros序列化的是多个英雄对象 ) 关联对象序列化方案二:序列化成关联对象的__str__方法返回的结果 heros = serializers.StringRelatedField(many=True) 关联对象序列化方案三:自定义关联对象序列化 heros = HeroInfoSerializer(many=True)
serializers.py
class BookInfoSerializer(serializers.Serializer): btitle = serializers.CharField() bpub_date = serializers.DateField() bread = serializers.IntegerField() bcomment = serializers.IntegerField() is_delete = serializers.BooleanField() image = serializers.ImageField() class HeroInfoSerializer(serializers.Serializer): id = serializers.IntegerField() hname = serializers.CharField() hgender = serializers.IntegerField() hcomment = serializers.CharField() is_delete = serializers.BooleanField() 代表当前英雄对象(从),关联的书本(主)单一对象 hbook = serializers.PrimaryKeyRelatedField( queryset=BookInfo.objects.all() ) hbook = serializers.StringRelatedField() hbook = BookInfoSerializer()
三种形式说明
(1)、PrimaryKeyRelatedField(queryset,many)
(2)、StringRelatedField()
(3)、自定义序列化器
(1)获取有效数据
book_info = {"btitle": "围城", "bpub_date": "1999-9-9"}
(2)实例化序列器对象
bs = BookInfoSerializer(data=book_info, partial=True)
data是要被校验的数据,partial为True是部分校验,有什么就校验什么
(3)启动校验流程
bs.is_valid()
# 通过抛ValidationError异常的方式表示失败
# bs.is_valid(raise_exception=True)
当调用is_valid()方法即开始校验,包括约束条件校验、类型校验、validators校验、validate_<字段名>校验、validate校验,若全部校验通过返回True,否则返回False
(4)获得最终结果
若校验成功,查看有效数据
bs.validated_data
若校验失败,查看失败信息
bs.errors
(3)自定义校验之1:validators
serializers.py
# 针对btitle字段,自定义一个校验函数
def check_btitle(value):
if "django" not in value:
raise serializers.ValidationError("这不是一本关于django的书")
class BookInfoSerializer(serializers.Serializer):
# validators指定多个针对当前字段的校验函数)
btitle = serializers.CharField(其他校验,validators=[check_btitle]
...
(3)自定义校验之2:validate_<字段名>
serializers.py
class BookInfoSerializer(serializers.Serializer):
...
btitle = serializers.CharField(label='名称',max_length=20,)
# 重写序列化器特定名称的方法,针对特定字段单独自定义校验,函数名称:validate_<被校验字段名>
def validate_btitle(self, value):
if "django" not in value:
raise serializers.ValidationError("这不是一本关于django的书")
# 切记,一定要返回字段的有效值,如果不返回会造成当前字段数据丢失
return value
(3)自定义校验之3:validate
serializers.py
class BookInfoSerializer(serializers.Serializer):
...
btitle = serializers.CharField(label='名称',max_length=20,)
def validate(self, attrs):
# 提取数据
btitle = attrs.get('btitle')
if 'django' not in btitle:
raise serializers.ValidationError('这不是一本关于django的书')
# 相同方式对别的字段校验...略
# 返回最终的有效数据,如果不返回,后果就是丢失最终的有效数据
return attrs
第3种校验方式最常用,因为它可以对所以字段进行自定义校验
前端传过来的数据要写进数据库,可能是新建一条新的数据,也可能只是更新部分字段,在调用save()方法的时候会执行新建或更新操作
实例化序列号器对象的时候,如果只传入data不传instance即为新建,若两者都传即为更新数据,
新建和更新的本质是调用我们在序列化器重写的create()和update()这两个方法
serializers.py
class BookInfoSerializer(serializers.Serializer):
btitle = serializers.CharField(label='名称',max_length=20)
...
def create(self, validated_data):
instance = BookInfo.objects.create(**validated_data) # create(btitle="django精通"....)
return instance
def update(self, instance, validated_data):
for field,value in validated_data.items():
# field = "btitle"; value = "django精通新版"
setattr(instance, field, value)
instance.save()
return instance
举例
book_info = {"btitle": "django精通"....}
book = BookInfo.objects.get(pk=6)
bs = BookInfoSerializer(instance=book, data=book_info)
bs.is_valid()
# 如果校验结果为True,则调用save()方法
bs.save()
# 全校验
Serializer(instance=模型类对象,data=参数)
# 部分校验(如更新部分字段操作)
Serializer(instance=模型类对象,data=参数,partial=True)
一般情况下是在实例化序列化器的时候就用data参数传输待校验的数据,但是后续可能需要指定其他字段,这时候可以在调用save()方法的时候传入其他参数
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。