首页 > 其他分享 >DRF教程文档解析(一)

DRF教程文档解析(一)

时间:2022-12-15 15:45:21浏览次数:32  
标签:教程 serializers btitle instance 文档 序列化 data serializer DRF

序列化器

  • 参考网址
    https://blog.csdn.net/weixin_35688430/article/details/111203136

  • 定义序列化器

# 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)
......
# serializer
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不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义
  **serializer是独立于数据库之外的存在
  • 重要参数
- read_only   表明该字段仅用于序列化输出,默认False

- write_only  表明该字段仅用于反序列化输入,默认False

创建Serializer对象

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

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

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

  • 除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据
    通过context参数附加的数据,可以通过Serializer对象的context属性获取。

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


- 序列化器的使用

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

    • 在客户端请求时,使用序列化器可以完成对数据的反序列化
      即把json转成python dict类型,后端处理数据

    • 在服务器响应时,使用序列化器可以完成对数据的序列化
      即把python dict类型转成json,返回给前端


- 序列化

  • 先查询出一个图书对象

from booktest.models import BookInfo
book = BookInfo.objects.get(id=2)

  • 构造序列化器对象

from booktest.serializers import BookInfoSerializer
serializer = BookInfoSerializer(book)

  • 获取序列化数据: 通过data属性可以获取序列化后的数据

serializer.data

{'id': 2, 'btitle': '天龙八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None}

  • 如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明

book_qs = BookInfo.objects.all()
serializer = BookInfoSerializer(book_qs, many=True)
serializer.data

[OrderedDict([('id', 2), ('btitle', '天龙八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bcomment', 40), ('image', N]), OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image'ne)]), OrderedDict([('id', 4), ('btitle', '雪山飞狐'), ('bpub_date', '1987-11-11'), ('bread', 58), ('bcomment', 24), ('ima None)]), OrderedDict([('id', 5), ('btitle', '西游记'), ('bpub_date', '1988-01-01'), ('bread', 10), ('bcomment', 10), ('im', 'booktest/xiyouji.png')])]


- 反序列化: 首先是数据校验

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

  • 调用is_valid()方法进行验证,验证成功返回True,否则返回False

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

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


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

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)
......

from booktest.serializers import BookInfoSerializer
data = {'bpub_date': 123}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # 返回False
serializer.errors

{'btitle': [ErrorDetail(string='This field is required.', code='required')], 'bpub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')]}

serializer.validated_data # {}

data = {'btitle': 'python'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # True
serializer.errors # {}

serializer.validated_data # OrderedDict([('btitle', 'python')])


- is_valid() 支持在校验失败的时候,直接抛异常,通过传递raise_exception=True参数开启

Return a 400 response if the data was invalid.

serializer.is_valid(raise_exception=True)


### 自定义验证有三种方法

- validate_field钩子(注意,不要写成 validated_field)
  钩子的意味着方法名称一定要写死,写固定的,错一个字符都不会被调用!

class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
...

def validate_btitle(self, value): # value就是用户传入的值
    if 'django' not in value.lower():
        raise serializers.ValidationError("图书不是关于Django的")
    return value # 校验无误,就返回value

......
from booktest.serializers import BookInfoSerializer
data = {'btitle': 'python'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # False
serializer.errors

{'btitle': [ErrorDetail(string='图书不是关于Django的', code='invalid')]}


- validate()方法: 多个字段一起校验 

class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
...

def validate(self, attrs): # attrs是一个字典,包含用户输入的值
    bread = attrs['bread']
    bcomment = attrs['bcomment']
    if bread < bcomment:
        raise serializers.ValidationError('阅读量小于评论量')
    return attrs # 校验无误,返回字段

......

from booktest.serializers import BookInfoSerializer
data = {'btitle': 'about django', 'bread': 10, 'bcomment': 20}
s = BookInfoSerializer(data=data)
s.is_valid() # False

s.errors

{'non_field_errors': [ErrorDetail(string='阅读量小于评论量', code='invalid')]}


- validators选项参数,可以对单个字段进行校验(支持多个验证)

def about_django(value):
if 'django' not in value.lower():
raise serializers.ValidationError("图书不是关于Django的")

class BookInfoSerializer(serializers.Serializer):
...... # 支持传入多个函数验证对象
btitle = serializers.CharField(label='名称', max_length=20, validators=[about_django])
......
from booktest.serializers import BookInfoSerializer
data = {'btitle': 'python'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # False
serializer.errors

{'btitle': [ErrorDetail(string='图书不是关于Django的', code='invalid')]}


- 还有一个 extra_kwargs 配置项也可以作验证

class RegisterSerializer(serializers.ModelSerializer):

password2 = serializers.CharField(write_only=True, label='重复密码')
sms_code = serializers.CharField(write_only=True, label='短信验证码')
allow = serializers.CharField(write_only=True, label='是否同意协议')
token = serializers.CharField(read_only=True, label='token')

class Meta:
    model = UserInfo
    fields = ['id', 'username', 'password', 'password2', 'mobile', 'sms_code', 'allow','token']
    extra_kwargs = {  # 修改字段选项(作基本的校验)
        'username': {
            'min_length': 5,
            'max_length': 20,
            'error_messages': {
                'min_length': '仅允许5-20个字符的用户名',
                'max_length': '仅允许5-20个字符的用户名',
            }
        },
        'password': {
            'write_only': True,
            'min_length': 8,
            'max_length': 20,
            'error_messages': {
                'min_length': '仅允许8-20个字符的用户名',
                'max_length': '仅允许8-20个字符的用户名',
            }
        },
    }

### 反序列化-保存数据

- 数据校验成功后,可以使用序列化器来完成数据反序列化的过程(把数据转成模型类对象,存入db/更新db)
  可以通过实现create()和update()两个方法来实现

class BookInfoSerializer(serializers.Serializer):
......
def create(self, validated_data):
# 这里为什么可以直接存?因为前面已经调用 is_valid(),数据校验无误了
return BookInfo(**validated_data)

def update(self, instance, validated_data):
    """更新,instance为要更新的对象实例,校验过的数据,从validated_data取即可"""
    instance.btitle = validated_data.get('btitle', instance.btitle)
    instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
    instance.bread = validated_data.get('bread', instance.bread)
    instance.bcomment = validated_data.get('bcomment', instance.bcomment)
    return instance # 最后返回更新过的实例
- 如果需要在返回数据对象的时候,也将数据保存到数据库中,可以这么搞

class BookInfoSerializer(serializers.Serializer):
......
def create(self, validated_data):
# return BookInfo(validated_data)
return BookInfo.objects.create(
validated_data)

def update(self, instance, validated_data):
    instance.btitle = validated_data.get('btitle', instance.btitle)
    instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
    instance.bread = validated_data.get('bread', instance.bread)
    instance.bcomment = validated_data.get('bcomment', instance.bcomment)
    instance.save() # 调用save()方法存入db
    return instance

......

  • 实现了上述两个方法后,在反序列化数据的时候,就可以通过save()方法返回一个模型实例
    book = serializer.save()

- 如果创建序列化器对象的时候,没有传递instance实例,则调用save()方法的时候,create()被调用
  相反,如果传递了instance实例,则调用save()方法的时候,update()被调用
  简而言之,有传instance,就是更新,自动调用update;
  没有传递instance,就是创建,自动调用create;

通过save(),把数据存入db

Copyfrom db.serializers import BookInfoSerializer
data = {'btitle': '封神演义'}
serializer = BookInfoSerializer(data=data) # 没有传递instance,则调用save()方法的时候,create()被调用
serializer.is_valid() # True
serializer.save() # <BookInfo: 封神演义>

通过save(),更新db数据

from db.models import BookInfo
book = BookInfo.objects.get(id=2)
data = {'btitle': '倚天剑'}
serializer = BookInfoSerializer(book, data=data) # 传递了instance,则调用save()方法的时候,update()被调用
serializer.is_valid() # True
serializer.save() # <BookInfo: 倚天剑>
book.btitle # '倚天剑'


### 附加说明

- 在对序列化器进行save()保存时,可以额外传递数据
  这些数据可以在create()和update()中的validated_data参数获取到

serializer.save(owner=request.user)


- 默认序列化器必须传递所有required的字段,否则会抛出验证异常
  但是我们可以使用partial参数来允许部分字段更新

Update comment with partial data

serializer = CommentSerializer(comment, data={'content': 'foo bar'}, partial=True)

标签:教程,serializers,btitle,instance,文档,序列化,data,serializer,DRF
From: https://www.cnblogs.com/qinganning/p/16985160.html

相关文章

  • 双 11 抢购项目部署文档
    本文档中主要描述如何进行双11抢购项目的本地运行和部署。1、环境说明1)服务器配置内存16G+(DDR3或以上)CPU标准电压版i5(3470+)4核单线程(双线程更好)硬盘5......
  • 离线安装mysql5.7【教程二】
    openjdk1.8文件下载链接地址:链接:https://pan.baidu.com/s/1fLt_dNILuw5VsV_PcA_yAQ提取码:ot3emysql5.7安装包下载链接地址:链接:https://pan.baidu.com/s/1du7Dk7WtJ0Ac......
  • 「Docker学习系列教程」基础篇小总结及高级篇预告
    通过前面十来篇的学习,我们已经把docker基础篇学习完了。这篇文章,咱们就来小总结下基础篇学习的东西以及介绍接下来高级篇中,将会学习到哪些知识点。 基础篇总结:第一篇,......
  • opencl 教程
    这是第一篇真正的OpenCL教程。这篇文章不会从GPU结构的技术概念和性能指标入手。我们将会从OpenCL的基础API开始,使用一个小的kernel作为例子来讲解基本的计算管理。首先我......
  • 桥接网络配置模式文档1
    桥接网络配置模式文档使用虚拟机vmware 版本15创建好虚拟机以后配置选择桥接模式实现网段最后的互通 2 点击设置后选择桥接模式   3 点击编辑选择虚拟网络......
  • 无忧·企业文档,为企业客户的场景而思考
    作为无忧企业文档的设计者,常常被问到一个问题,这个和腾X文档有什么区别?其实这个问题我口头回答了很多次,这次,我将这个问题做个记录与分析。主要是有以下几个方面不同:1、客户定......
  • IIS功能缺失(没有日志或默认文档)
    我发现我的IIS少了好多功能,但是忘记是哪里设置打开的了,找了很久,发现是在控制面板里面。。。       一个一个仔细打开,把对应的勾上,提交之后就会把这些功能......
  • Zabbix6.0使用教程 (五)—zabbix从二进制包安装上篇
    大家好,我是乐乐。上一期我们已经讲过从源代码安装zabbix,本期着重讲从二进制包安装zabbix。  当我们在ZABBIX官方存储库可以看到,ZabbixSIA提供如下官方RPM和DEB包:......
  • Zabbix6.0使用教程 (四)—zabbix6.0从源代码安装
    接上篇zabbix部署安装前置要求,本期我们将先讲讲如何从源代码安装zabbix6.0,还在为如何安装使用zabbix的小伙伴可以仔细看看。一、安装Zabbix守护进程1下载源代码压缩包......
  • IntelliJ IDEA 下载安装及配置使用教程(图文步骤详解)
    前言壹哥在前面的文章中,带大家下载、安装、配置了Eclipse这个更好用的IDE开发工具,并教会了大家如何在Eclipse中进行项目的创建和代码编写、运行。但是实际上,在各种IDE开发......