定义Serializer

1. 定义方法

Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。

例如,我们已有了一个数据库模型类BookInfo

  1. class BookInfo(models.Model):
  2. btitle = models.CharField(max_length=20, verbose_name='名称')
  3. bpub_date = models.DateField(verbose_name='发布日期', null=True)
  4. bread = models.IntegerField(default=0, verbose_name='阅读量')
  5. bcomment = models.IntegerField(default=0, verbose_name='评论量')
  6. image = models.ImageField(upload_to='booktest', verbose_name='图片', null=True)

我们想为这个模型类提供一个序列化器,可以定义如下:

  1. class BookInfoSerializer(serializers.Serializer):
  2. """图书数据序列化器"""
  3. id = serializers.IntegerField(label='ID', read_only=True)
  4. btitle = serializers.CharField(label='名称', max_length=20)
  5. bpub_date = serializers.DateField(label='发布日期', required=False)
  6. bread = serializers.IntegerField(label='阅读量', required=False)
  7. bcomment = serializers.IntegerField(label='评论量', required=False)
  8. image = serializers.ImageField(label='图片', required=False)

注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。

2. 字段与选项

常用字段类型

read_only:True表示不允许用户自己上传,只能用于api的输出。如果某个字段设置了read_only=True,那么就不需要进行数据验证,只会在返回时,将这个字段序列化后返回

write_only:与read_only对应;就是用户post过来的数据,后台服务器处理后不会再经过序列化后返回给客户端;最常见的就是我们在使用手机注册的验证码和填写的密码。

3. 创建Serializer对象

Serializer的构造方法为:

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

说明:

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

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

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

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

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

Serializer使用

我们定义一个测试视图来使用序列化器,如下:

views

  1. def test(request):
  2. return HttpResponse('ok')

urls

  1. urlpatterns = [
  2. url(r'^test/$', views.test)
  3. ]

1. 基本使用

  1. def test(request):
  2. book = BookInfo.objects.get(id=5) # 先查询出一个图书对象
  3. serializer = BookInfoSerializer(book) # 构建序列化
  4. print(serializer.data) # 获取序列化数据 {'image': None, 'btitle': '西游记', 'id': 5, 'bread': 10, 'bcomment': 10, 'bpub_date': '1988-01-01'}
  5.  
  6. return HttpResponse('ok')

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

  1. def test(request):
  2. book = BookInfo.objects.all() # 先查询出一个图书对象
  3. serializer = BookInfoSerializer(book, many=True) # 构建序列化
  4. print(serializer.data) # 获取序列化数据 {'image': None, 'btitle': '西游记', 'id': 5, 'bread': 10, 'bcomment': 10, 'bpub_date': '1988-01-01'}
  5.  
  6. return HttpResponse('ok')

2. 关联对象嵌套序列化

如果需要序列化的数据中包含有其他关联对象,则对关联对象数据的序列化需要指明。

例如,在定义英雄数据的序列化器时,外键hbook(即所属的图书)字段如何序列化?

我们先定义HeroInfoSerialzier除外键字段外的其他部分

对于关联字段,可以采用以下几种方式:

1. PrimaryKeyRelatedField

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

  1. hbook = serializers.PrimaryKeyRelatedField(label='图书', read_only=True)

  2. hbook = serializers.PrimaryKeyRelatedField(label='图书', queryset=BookInfo.objects.all())

指明字段时需要包含read_only=True或者queryset参数:

  • 包含read_only=True参数时,该字段将不能用作反序列化使用

  • 包含queryset参数时,将被用作反序列化时参数校验使用

使用效果:

  1. def test(request):
  2. hero = HeroInfo.objects.get(id=10) # 查询一个英雄对象
  3. serializer = HeroInfoSerializer(hero) # 构建序列化
  4. print(serializer.data) # 返回序列化内容 {'id': 10, 'hcomment': '独孤九剑', 'hname': '令狐冲', 'hbook': 3, 'hgender': 1}
  5. return HttpResponse('ok')

报错:说明id不存在

2. StringRelatedField

此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)

  1. hbook = serializers.StringRelatedField(label='图书')
  1. def test(request):
  2. hero = HeroInfo.objects.get(id=11) # 查询一个英雄对象
  3. serializer = HeroInfoSerializer(hero) # 构建序列化
  4. print(serializer.data) # 返回序列化内容 {'hgender': 0, 'hbook': '笑傲江湖', 'id': 11, 'hname': '任盈盈', 'hcomment': '弹琴'}
  5. return HttpResponse('ok')
3. 使用关联对象的序列化器
  1. hbook = BookInfoSerializer()
  1. def test(request):
  2. hero = HeroInfo.objects.get(id=11) # 查询一个英雄对象
  3. serializer = HeroInfoSerializer(hero) # 构建序列化
  4. print(serializer.data) # 返回序列化内容 {'hgender': 0, 'hbook': OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image', None)]), 'hcomment': '弹琴', 'id': 11, 'hname': '任盈盈'}
  5. return HttpResponse('ok')
4. HyperlinkedRelatedField

此字段将被序列化为获取关联对象数据的接口链接

  1. hbook = serializers.HyperlinkedRelatedField(label='图书', read_only=True, view_name='books-detail')

必须指明view_name参数,以便DRF根据视图名称寻找路由,进而拼接成完整URL。

  1. {'id': 6, 'hname': '乔峰', 'hgender': 1, 'hcomment': '降龙十八掌', 'hbook': 'http://127.0.0.1:8000/books/2/'}
5. SlugRelatedField

此字段将被序列化为关联对象的指定字段数据

slug_field指明使用关联对象的哪个字段

  1. hbook = serializers.SlugRelatedField(label='图书', read_only=True, slug_field='bpub_date')
  1. def test(request):
  2. hero = HeroInfo.objects.get(id=11) # 查询一个英雄对象
  3. serializer = HeroInfoSerializer(hero) # 构建序列化
  4. print(serializer.data) # 返回序列化内容 {'id': 11, 'hgender': 0, 'hcomment': '弹琴', 'hname': '任盈盈', 'hbook': datetime.date(1995, 12, 24)}
  5.  
  6. return HttpResponse('ok')
6. 重写to_representation方法

序列化器的每个字段实际都是由该字段类型的to_representation方法决定格式的,可以通过重写该方法来决定格式。

注意,to_representations方法不仅局限在控制关联对象格式上,适用于各个序列化器字段类型。

自定义一个新的关联字段:

  1. class BookRelateField(serializers.RelatedField):
  2. """自定义用于处理图书的字段"""
  3. def to_representation(self, value):
  4. return 'Book: %d %s' % (value.id, value.btitle)
  1. hbook = BookRelateField(read_only=True)
  1. def test(request):
  2. hero = HeroInfo.objects.get(id=11) # 查询一个英雄对象
  3. serializer = HeroInfoSerializer(hero) # 构建序列化
  4. print(serializer.data) # 返回序列化内容 {'hbook': 'Book: 3 笑傲江湖', 'id': 11, 'hcomment': '弹琴', 'hname': '任盈盈', 'hgender': 0}
  5. return HttpResponse('ok')

many参数

如果关联的对象数据不是只有一个,而是包含多个数据,如想序列化图书BookInfo数据,每个BookInfo对象关联的英雄HeroInfo对象可能有多个,此时关联字段类型的指明仍可使用上述几种方式,只是在声明关联字段时,多补充一个many=True参数即可。

此处仅拿PrimaryKeyRelatedField类型来举例,其他相同。

在BookInfoSerializer中添加关联字段:

  1. class BookInfoSerializer(serializers.Serializer):
  2. """图书数据序列化器"""
  3. id = serializers.IntegerField(label='ID', read_only=True)
  4. btitle = serializers.CharField(label='名称', max_length=20)
  5. bpub_date = serializers.DateField(label='发布日期', required=False)
  6. bread = serializers.IntegerField(label='阅读量', required=False)
  7. bcomment = serializers.IntegerField(label='评论量', required=False)
  8. image = serializers.ImageField(label='图片', required=False)
  9. heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增

使用效果:

  1. def test(request):
  2. book = BookInfo.objects.get(id=3) # 查询一个英雄对象
  3. serializer = BookInfoSerializer(book) # 构建序列化
  4. print(serializer.data) # 返回序列化内容 {'image': None, 'id': 3, 'bpub_date': '1995-12-24', 'bcomment': 80, 'bread': 20, 'heroinfo_set': [10, 11, 12, 13], 'btitle': '笑傲江湖'}
  5.  
  6. return HttpResponse('ok')

Serializer序列器的更多相关文章

  1. Android初级教程:使用xml序列器

    之前备份短信的时候生成xml都是手动拼写的,有一个问题:当短信里面存在</body>这样的标签的时候,最后结果就不是完整的xml文件,显然出错.但是,今天使用序列化器的方式,就能有效的解决 ...

  2. DRF框架之Serializer序列化器的序列化操作

    在DRF框架中,有两种序列化器,一种是Serializer,另一种是ModelSerializer. 今天,我们就先来学习一下Serializer序列化器. 使用Serializer序列化器的开发步骤 ...

  3. DRF框架之Serializer序列化器的反序列化操作

    昨天,我们完成了Serializer序列化器的反序列化操作,那么今天我们就来学习Serializer序列化器的最后一点知识,反序列化操作. 首先,我们定要明确什么是反序列化操作? 反序列化操作:JOS ...

  4. DRF 序列化器-Serializer (2)

    作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器 ...

  5. 16-DRF工程搭建与序列化器

    1.DRF工程搭建 环境安装与配置 DRF是以Django扩展应用的方式提供的,所以我们可以直接利用Django环境,而无需创建(先创建Django环境). 1.安装DRF pip3 install ...

  6. Django:前后端分离 djangorestframework开发API接口 serializer序列化认证组件

    参考:https://blog.csdn.net/zhangmengran/article/details/84887206 目的: 使用serializer序列化器将QuerySet数据序列化为js ...

  7. Django 学习之Django Rest Framework_序列化器_Serializer

    作用: 1.序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串. 2.反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型. 3 ...

  8. drf Serializer使用

    drf序列化 在前后端不分离的项目中,可以使用Django自带的forms组件进行数据验证,也可以使用Django自带的序列化组件对模型表数据进行序列化. 那么在前后端分离的项目中,drf也提供了数据 ...

  9. DjangoRestFramework学习二之序列化组件、视图组件 serializer modelserializer

      DjangoRestFramework学习二之序列化组件.视图组件   本节目录 一 序列化组件 二 视图组件 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 序列化组 ...

随机推荐

  1. Quality of Service (QoS) in LTE

    Background: Why we need QoS ? There are premium subscribers who always want to have better user expe ...

  2. mysql忘记数据库密码

    1.停止mysql服务 2.以管理员身份开启命令行,进入mysql文件夹,mysqld --skip-grant-tables 3.另外以管理员身份开启一个命令行,直接输入mysql,就可以进入数据库 ...

  3. jQuery获取url

    JS获取当前页面的URL信息 设置或获取对象指定的文件名或路径. <script> alert(window.location.pathname) </script> 设置或获 ...

  4. Backbone源码解析系列

    01 编码风格.继承 02 Backbone.Events 03 Backbone.Model 04 Backbone.View 05 Backbone.Router 06 Backbone应用于we ...

  5. 学习笔记:location.hash和history.pushState()

    在浏览器中改变地址栏url,将会触发页面资源的重新加载,这使得我们可以在不同的页面间进行跳转,得以浏览不同的内容.但随着单页应用的增多,越来越多的网站采用ajax来加载资源.因为异步加载的特性,地址栏 ...

  6. pscp no such file or directory

    背景:在WINDOWS10 上传一个文件 到 Centos 7中 工具:pscp 用法: pscp.exe -C e:\tinyfox\site\wwwroot\cdms\projecttemplat ...

  7. ArrayList与Vector区别

    ArrayList与Vector区别表 ArrayList Vector 1.实现原理:采用动态对象数组实现,默认构造方法创建了一个空数组 1.实现原理:采用动态数组对象实现,默认构造方法创建了一个大 ...

  8. C# 发Domino邮件 报错误 Password or other security violation for database 的解决方案

    错误提示: Password or other security violation for database ******* 问题产生的描述: 之前C#发邮件是好的 加上了附件部分代码之后,出现了这 ...

  9. C#高性能Socket服务器IOCP实现

    引言我一直在探寻一个高性能的Socket客户端代码.以前,我使用Socket类写了一些基于传统异步编程模型的代码(BeginSend.BeginReceive,等等)也看过很多博客的知识,在linux ...

  10. IOS UISwitch控件的基本使用

    * UISwitch继承自UIControl,因此也能像UIButton一样监听一些事件,比如状态改变事件* UISwitch可以通过拖线监听状态改变* UISwitch可以通过addTarget:. ...