REST Framework概述

Django REST framework是一套基于Django的REST框架,是一个用于构建Web API的功能强大且灵活的工具包。

1.RESTful 简述
Representational State Transfer(REST),是一种架构样式,定义了一套用于创建WEB服务的约束。当前WEB开发趋势就是前端层出不穷,为了保证一个后台同时适用于多个前端,需要一种统一的机制或API,而RESTful API是目前前后端分离的最佳实践。

2.为什么需要前后端分离?
--PC,APP,Pad 等多端适应;
--SPA开发模式流行(Single Page web Application);
--使得前后端开发职责清楚,提高开发效率高;
--避免了开发语言和模板语言的高度耦合和开发语言之间的依赖;

3.RESTful API特点
--轻量,直接通过HTTP协议,不需要额外的协议;
--面向资源,每一个URL代表一种资源,具有自解释性;
--数据描述简单,一般通过JSON、xml做数据通信;
--客户端根据不同的请求,通过不同的HTTP方法(get、post、delete、put),对服务器资源进行操作。

4.为什么要使用Django REST 框架而不是Django?
虽然Django中可以通过DTL(Django Template Language)来实现PC端的显示,但却无法支持如Android端、ios端。而且Django只能依赖DTL实现PC端的显示。

要实现一套后台适应多个前端,就必须使用前后端分离技术,因此就要使用RESTful API,而Django REST框架正是基于Django的RESTful API。

安装Django REST Framework

1.通过如下命令安装REST 框架:

  1. $ pip install djangorestframework

2.如果没有安装Python,则需要安装Python和Django:

  1. $ sudo apt-get install python3.6
  2. $ sudo apt-get install python3-pip
  3. $ pip install Django

序列化和反序列化

序列化,是指将复杂的QuerySet和Model类型转换成Python基本数据类型,从而将这些基本数据类型以JSON的形式响应给客户端。

反序列化则和序列化相反,是指将Http请求中传入的JSON数据转换成复杂的数据类型,从而保存在数据库中。

1.在REST Framework中,提供了多个用于序列化操作的类,但常用的也就如下两个:

Serializer:进行序列化基本的类;

ModelSerializer:继承于Serializer,内部实现了通用的序列化逻辑,其中包含了与Model字段对应的字段,可以快速对Model进行序列化。

2.使用时需要导入对应模块

  1. from rest_framework import serializers

Serializer

1.Serializer进行序列化的基本格式如下:

  1. from rest_framework import serializers
  2.  
  3. class CommentSerializer(serializers.Serializer):
  4. # 指定要序列化的字段
  5. email = serializers.EmailField()
  6. content = serializers.CharField(max_length=200)
  7. created = serializers.DateTimeField()
  8. # 用于反序列化时创建一个Model实例
  9. def create(self, validated_data):
  10. return Comment(**validated_data)
  11. # 用于反序列化时更新一个Model实例
  12. def update(self, instance, validated_data):
  13. # ...
  14. instance.email = validated_data.get('email',instance=emial)
  15. # ...
  16. return instance

2.接下来我们看看在REST框架中如何对一个Model进行序列化操作

Step1.创建一个model:

  1. from django.db import models
  2.  
  3. class Student(models.Model):
  4. name = models.CharField(max_length=40)
  5. age = models.IntegerField()
  6. number = models.IntegerField(unique=True)
  7. date = models.DateField()

Step2.创建对该Model进行序列化的类:

在app/下创建serializer.py文件

  1. from rest_framework import serializers
  2. from .models import Student
  3.  
  4. class StudentSerializer(serializers.Serializer):
  5. # 定义要序列化的字段
  6. name = serializers.CharField(read_only=True)
  7. age = serializers.IntegerField(read_only=True)
  8. number = serializers.IntegerField(read_only=True)
  9. date = serializers.DateField(read_only=True)
  10.  
  11. # 在反序列化时,当save()调用时生成一个Student对象
  12. def create(self, validated_data):
  13. # 会将生成的实例保存到数据库
  14. return Student.objects.create(**validated_data)
  15.  
  16. # 在反序列化时,当save()调用时更新Student对象
  17. def update(self, instance, validated_data):
  18.  
  19. instance.name = validated_data.get('name', instance.name)
  20. instance.age = validated_data.get('age', instance.age)
  21. instance.number = validated_data.get('number', instance.number)
  22. instance.date = validated_data.get('date', instance.date)
  23. instance.save() #确保保存在数据库
  24. return instance

3.这个序列化类中有两部分:

1.定义了要进行序列化的字段;这些字段负责将Python类型转换成JSON类型,即序列化的过程;
2.定义了当serializer.save()时用于生成Model对象的create()和update()方法,这两方法负责将JSON类型的数据转换成Python类型的数据,即反序列化的过程。
整个序列化类的实现就这么简单,接下来我们还需要对这个序列化类进行测试。

测试Serializer有两种方式,一种是在Django Shell下进行测试,还有一种就是直接创建一个View,通过http请求进行测试,如果掌握了如何创建view,那么请直接在View中进行吧!

Step3.在Django shell下进行序列化测试:
使用python manage.py shell进入Django Shell中:

  1. >>> from Students.models import Student # 导入对应module
  2. >>> from Students.serializers import StudentSerializer
  3. >>> stu = Student(name='zhangsan',age=21,number=1,date='2018-4-23') #创建一个Model实例
  4. >>> stu.save()   # 将该实例存入数据库
  5. >>> serializer = StudentSerializer(stu)   #进行序列化
  6. >>> serializer.data  # 查看序列化后的结果
  7. {'name': 'zhangsan', 'age': 21, 'number': 1, 'date': '2018-4-23'}

现在将Student实例转换成了Python中的dict类型,接下来将dict类型转换为JSON数据:

  1. >>> from rest_framework.renderers import JSONRenderer #JSONRenderer将数据渲染称JSON格式
  2. >>> content = JSONRenderer().render(serializer.data)
  3. >>> content
  4. b'{"name":"zhangsan","age":21,"number":1,"date":"2018-4-23"}'
  5. >>>

反序列化类似,第一步是将JSON形式数据转换为流的形式,并将流数据转化为python本地数据类型:

  1. >>> from django.utils.six import BytesIO
  2. >>> from rest_framework.parsers import JSONParser
  3. >>> stream = BytesIO(content) # 将JSON数据转换为流的形式
  4. >>> data = JSONParser().parse(stream) # JSONParser将解析流中的JSON数据,得到Python的类型数据
  5. >>> data
  6. {'name': 'zhangsan', 'age': 21, 'number': 1, 'date': '2018-4-23'} # 一个dict类型的数据
  7. >>>

然后将Python本地类型转换为实例,保存在数据库中:

  1. >>> serializer = StudentSerializer(data=data)
  2. >>> serializer.is_valid() # 验证是否有效
  3. >>> True
  4. >>> serializer.save() # 将保存在数据库中

该例中是序列化了一个Model对象,如果要序列化由Model.objects.all()返回的一个QuerySet实例,在设置serializer时添加一个参数:

  1. >>> serializer = StudentSerializer(Student.objects.all(), many=True)
  2. >>> serializer.data
  3. >>>

虽然这种方式略显麻烦,但对于初学者来说,掌握Django shell还是很有用的。 
如果对View相关知识了解,那么可以非常方便的在View中通过Http请求进行验证,如下是通过GET请求和POST请求用于验证Serializer:

  1. from rest_framework import views
  2. from rest_framework.response import Response
  3. from rest_framework import status
  4. from . import models
  5. from .serializers import StudentSerializer
  6. # Create your views here.
  7.  
  8. class show(views.APIView):
  9.  
  10. def get(self, request):
  11. """
  12. get方法处理GET请求
  13. """
  14. try:
  15. Student = models.Student.objects.all()
  16. # Student是一个QuerySet,而不是一个Model对象,因此需要设置many=True
  17. serializer = StudentSerializer(Student, many=True)
  18. return Response(serializer.data, status=status.HTTP_200_OK)
  19. except Student.DoesNotExist:
  20. return Response(serializer.data, status=status.HTTP_404_NOT_FOUND)
  21.  
  22. def post(self, request):
  23. """
  24. post方法处理POST请求
  25. """
  26. # request.data是请求体中经过解析后的数据
  27. serializer = StudentSerializer(data=request.data)
  28. if serializer.is_valid(): # 检验是否有效
  29. serializer.save() # 将会调用Serializer中的create(),并保存在数据库中
  30. # serializer.data是序列化后的原始数据
  31. # rest_framework.status中定义了常见返回值,如404,200...
  32. return Response(serializer.data, status=status.HTTP_201_CREATED)
  33.  
  34. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Serializer的方法和属性

1.save()

在调用serializer.save()时,会创建或者更新一个Model实例(调用create()update()创建),具体根据序列化类的实现而定,如:

  1. # .save() will create a new instance.
  2. serializer = StudentSerializer(data=data)
  3.  
  4. # .save() will update the existing `comment` instance.
  5. serializer = StudentSerializer(comment, data=data)

2.create()、update()

Serializer中的create()和update()方法用于创建生成一个Model实例,在使用Serializer时,如果要保存反序列化后的实例到数据库,则必须要实现这两方法之一,生成的实例则作为save()返回值返回。方法属性validated_data表示校验的传入数据。

3. is_valid()

当反序列化时,在调用Serializer.save()之前必须要使用is_valid()方法进行校验,如果校验成功返回True,失败则返回False,同时会将错误信息保存到serializer.errors属性中。

4.data

serializer.data中保存了序列化后的数据。

5.errors

当serializer.is_valid()进行校验后,如果校验失败,则将错误信息保存到serializer.errors属性中。

Serializer中的Field

在定义Model时,我们通过models.<FieldName>获取了各种不同的字段,作为数据库中表的一个列。而在Serializer中,也需要通过`serializers.<FieldName>的形式获取对应Model的字段,用来在JSON数据和Python数据类型之间进行转换,此外还可以根据Field中传入的属性进行校验、设置默认值。以下对常用Serializer的Field进行整理。

使用时,需要导入所在模块:

  1. from rest_framework import serializers

1.CharField

对应models.CharField,同时如果指定长度,还会负责校验文本长度。

max_length:最大长度;
min_length:最小长度;
allow_blank=True:表示允许将空串做为有效值,默认False;

2.EmailField

对应models.EmailField,验证是否是有效email地址。

3.IntegerField

对应models.IntegerField,代表整数类型

4.FloatField

对应models.FloatField,代表浮点数类型

5.DateTimeField

对应models.DateTimeField,代表时间和日期类型。

format='YYYY-MM-DD hh:mm':指定datetime输出格式,默认为DATETIME_FORMAT值。
需要注意,如果在 ModelSerializer 和HyperlinkedModelSerializer中如果models.DateTimeField带有auto_now=True或者auto_add_now=True,则对应的serializers.DateTimeField中将默认使用属性read_only=True,如果不想使用此行为,需要显示对该字段进行声明:

  1. class CommentSerializer(serializers.ModelSerializer):
  2. created = serializers.DateTimeField()
  3.  
  4. class Meta:
  5. model = Comment

6.FileField

对应models.FileField,代表一个文件,负责文件校验。

max_length:文件名最大长度;
allow_empty_file:是否允许为空文件;

7.ImageField
对应models.ImageField,代表一个图片,负责校验图片格式是否正确。

max_length:图片名最大长度;
allow_empty_file:是否允许为空文件

如果要进行图片处理,推荐安装Pillow: pip install Pillow

8.HiddenField

这是serializers中特有的Field,它不根据用户提交获取值,而是从默认值或可调用的值中获取其值。一种常见的使用场景就是在Model中存在user_id作为外键,在用户提交时,不允许提交user_id,但user_id在定义Model时又是必须字段,这种情况下就可以使用HiddenField提供一个默认值:

  1. class LeavingMessageSerializer(serializers.Serializer):
  2.  
  3. user = serializers.HiddenField(
  4. default=serializers.CurrentUserDefault()
  5. )

serializers.Field中的公共参数

所谓公共参数,是指对于所有的serializers.<FieldName>都可以接受的参数。以下是常见的一些公共参数。

1.read_only

read_only=True表示该字段为只读字段,即对应字段只用于序列化时(输出),而在反序列化时(创建对象)不使用该字段。默认值为False

2.write_only

write_only=True表示该字段为只写字段,和read_only相反,即对应字段只用于更新或创建新的Model时,而在序列化时不使用,即不会输出给用户。默认值为False。

3.required
required=False表示对应字段在反序列化时是非必需的。在正常情况下,如果反序列化时缺少字段,则会抛出异常。默认值为True。

4.default
给字段指定一个默认值。需要注意,如果字段设置了default,则隐式地表示该字段已包含required=False,如果同时指定default和required,则会抛出异常。

5.allow_null
allow_null=True表示在序列化时允许None作为有效值。需要注意,如果没有显式使用default参数,则当指定allow_null=True时,在序列化过程中将会默认default=None,但并不会在反序列化时也默认。

6.validators
一个应用于传入字段的验证函数列表,如果验证失败,会引发验证错误,否则直接是返回,用于验证字段,如:

  1. username = serializers.CharField(max_length=16, required=True, label='用户名',
  2. validators=[validators.UniqueValidator(queryset=User.objects.all(),message='用户已经存在')])

7.error_message

验证时错误码和错误信息的一个dict,可以指定一些验证字段时的错误信息,如:

  1. mobile= serializers.CharField(max_length=4, required=True, write_only=True, min_length=4,
  2. label='电话', error_messages={
  3. 'blank': '请输入验证码',
  4. 'required': '该字段必填项',
  5. 'max_length': '验证码格式错误',
  6. 'min_length': '验证码格式错误',
  7. })
8.style
一个键值对,用于控制字段如何渲染,最常用于对密码进行密文输入,如:
  1. password = serializers.CharField(max_length=16, min_length=6, required=True, label='密码',
  2. error_messages={
  3. 'blank': '请输入密码',
  4. 'required': '该字段必填',
  5. 'max_length': '密码长度不超过16',
  6. 'min_length': '密码长度不小于6',
  7.  
  8. },
  9. style={'input_type': 'password'}, write_only=True)
9.label

一个简短的文本字串,用来描述该字段。

10.help_text

一个文本字串,可用作HTML表单字段或其他描述性元素中字段的描述。

ModelSerializers

ModelSerializers继承于Serializer,相比其父类,ModelSerializer自动实现了以下三个步骤:

1.根据指定的Model自动检测并生成序列化的字段,不需要提前定义;
2.自动为序列化生成校验器;
3.自动实现了create()方法和update()方法。

1.使用ModelSerializer方式如下:

  1. class StudentSerializer(serializers.ModelSerializer):
  2. class Meta:
  3. # 指定一个Model,自动检测序列化的字段
  4. model = StudentSerializer
  5. fields = ('id', 'name', 'age', 'birthday')

相比于Serializer,可以说是简单了不少,当然,有时根据项目要求,可能也会在ModelSerializer中显示声明字段,这些在后面总结。

model

该属性指定一个Model类,ModelSerializer会根据提供的Model类自动检测出需要序列化的字段。默认情况下,所有Model类中的字段将会映射到ModelSerializer类中相应的字段。

fields
如果不希望对Model中所有的字符进行序列化,可以在fields属性中显示指定要进行序列化的字段。

Django REST Framework(一) Serializer和ModelSerializer的更多相关文章

  1. Django Restful Framework (二): ModelSerializer

    时常,你需要对django model 的实例进行序列化.ModelSerializer 类提供了一个捷径让你可以根据 Model 来创建 Serializer. ModelSerializer 类和 ...

  2. Django REST framework 第一章 Serialization

    此章节将会介绍多种构成REST framework的重要模块,在每个部分如何一起配合上提供一个综合的全方面的了解. 准备 同样的创建一个新项目,创建一个新的app,将rest_framework跟新建 ...

  3. Django Rest framework序列化流程

    目录 一 什么是序列化 二 Django REST framework配置流程之Serializer 三 Django REST framework配置流程之ModelSerializer 一 什么是 ...

  4. Sentry 开发者贡献指南 - Django Rest Framework(Serializers)

    Serializer 用于获取复杂的 python 模型并将它们转换为 json.序列化程序还可用于在验证传入数据后将 json 反序列化回 Python 模型. 在 Sentry,我们有两种不同类型 ...

  5. Django REST framework serializer 嵌套显示绝对路径

    在 Django REST framework官方文档提到,当调用Serializer时,应当传入request参数,以便生成完整的url而不是相对url.使用ModelSerializer时requ ...

  6. Django Rest framework基础使用之 serializer

    rest-framework文档地址:http://www.django-rest-framework.org/ Django Rest framework是一个非常强大且灵活的工具包,用于构建web ...

  7. Django Rest Framework Serializer的简单使用

    1.RESTful 1.1 定义 REST(Representational State Transfer)与技术无关,代表一种软件架构风格,中文为表征状态转移. 1.2 RESTful API设计 ...

  8. Django REST framework 的TokenAuth认证及外键Serializer基本实现

    一,Models.py中,ForeignKey记得要有related_name属性,已实现关联对象反向引用. app_name = models.ForeignKey("cmdb.App&q ...

  9. 利用 Django REST framework 编写 RESTful API

    利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...

随机推荐

  1. Error C2079 'CMFCPropertySheet::m_wndOutlookBar' uses undefined class 'CMFCOutlookBar'

    Severity Code Description Project File Line Suppression StateError C2079 'CMFCPropertySheet::m_wndOu ...

  2. Jenkins漏洞利用复现

    一.未授权访问 访问url: http://172.16.20.134:8080/script 命令执行 println "ls -al".execute().text 也可以利用 ...

  3. Vue中控制更新的方式

    一.  强制更新的实例方法   vm.$forceUpdate() 迫使 Vue 实例重新渲染.注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件. 在没有留意到数组或对象的变更检测注意事 ...

  4. .net core 基于AspNetCore.Identity+Identityserver4用户的权限管理

    一般权限控制,是先给角色分配对应权限,然后再给用户分配角色:总权限应该是在代码编写的时候就已经固定了,例如有个用户更新的接口,这里就会诞生一个用户更新的权限,接口在权限就在,没有接口也就没有了这个权限 ...

  5. Rocket - tilelink - BankBinder

    https://mp.weixin.qq.com/s/oZCYBdy5glxJQmYKVWvpvA   简单介绍BankBinder的实现.   ​​   1. 基本介绍   A BankBinder ...

  6. Java实现 LeetCode 706 设计哈希映射(数组+链表)

    706. 设计哈希映射 不使用任何内建的哈希表库设计一个哈希映射 具体地说,你的设计应该包含以下的功能 put(key, value):向哈希映射中插入(键,值)的数值对.如果键对应的值已经存在,更新 ...

  7. Java实现 LeetCode 304 二维区域和检索 - 矩阵不可变

    304. 二维区域和检索 - 矩阵不可变 给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2). Range Sum Qu ...

  8. Java实现 LeetCode 60 第k个排列

    60. 第k个排列 给出集合 [1,2,3,-,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: "123" &q ...

  9. SaaS权限设计总结

    2年前转到SaaS部门之后期间断断续续做着权限相关的业务,这篇文章主要回顾下过往的设计以及其原因和利弊. 不过因为是线上业务,会省略掉很多细节以及账号体系和权益相关得部分,只讨论权限相关. 本文也不会 ...

  10. Python 导入CSV、JSON、XML数据

    常见的机器可读格式包括: - 逗号分隔值(Comma-Separated Values,CSV)- 制表符分隔值(tab-separated values,TSV)- JavaScript 对象符号( ...