Day 79 django 的rest_framework 序列化器的序列化
在开发Web应用中,有两种应用模式:
1.前后端不分离
为了在团队内部形成共识、防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写的接口,用途一目了然,减少双方之间的合作成本。
目前市面上大部分公司开发人员使用的接口服务架构主要有:restful、rpc。
rpc: 翻译成中文:远程过程调用[远程服务调用].
post请求
action=get_all_student¶ms=301&sex=1
接口多了,对应函数名和参数就多了,前端在请求api接口时,就会比较难找.容易出现重复的接口
restful: 翻译成中文: 资源状态转换.
把后端所有的数据/文件都看成资源.
那么接口请求数据,本质上来说就是对资源的操作了.
web项目中操作资源,无非就是增删查改.所以要求在地址栏中声明要操作的资源是什么,然后通过http请求动词来说明对资源进行哪一种操作.
POST http://www.lufei.com/api/students/ 添加学生数据
GET http://www.lufei.com/api/students/ 获取所有学生
DELETE http://www.lufei.com/api/students/<pk> 删除1个学生
REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移。 它首次出现在2000年Roy Fielding的博士论文中。
RESTful是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中。
这种风格的理念认为后端开发任务就是提供数据的,对外提供的是数据资源的访问接口,所以在定义接口时,客户端访问的URL路径就表示这种要操作的数据资源。
而对于数据资源分别使用POST、DELETE、GET、UPDATE等请求动作来表达对数据的增删查改。

事实上,我们可以使用任何一个框架都可以实现符合restful规范的API接口。
参考文档:http://www.runoob.com/w3cnote/restful-architecture.html
api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把数据转换格式,序列化可以分两个阶段:
序列化: 把我们识别的数据转换成指定的格式提供给别人。
例如:我们在django中获取到的数据默认是模型对象,但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。
反序列化:把别人提供的数据转换/还原成我们需要的格式。
例如:前端js提供过来的json数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中。
核心思想: 缩减编写api接口的代码
中文文档:https://q1mi.github.io/Django-REST-framework-documentation/#django-rest-framework
github: https://github.com/encode/django-rest-framework/tree/master
特点
-
提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
-
提供了丰富的类视图、Mixin扩展类,简化视图的编写;
-
丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;
-
多种身份认证和权限认证方式的支持;[jwt]
-
内置了限流系统;
-
直观的 API web 界面;
-
可扩展性,插件丰富
6. 环境安装与配置
DRF需要以下依赖:
-
Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
-
Django (1.10, 1.11, 2.0)
DRF是以Django扩展应用的方式提供的,所以我们可以直接利用已有的Django环境而无需从新创建。(若没有Django环境,需要先创建环境安装Django)
# mkvirtualenv drfdemo -p python3 # 创建虚拟环境 # pip install django # 在虚拟环境中安装django pip install djangorestframework # 在虚拟环境中安装djangorestframework pip install pymysql # 在虚拟环境中安装pymysql
linux 里面复制快捷键 shift + insert ******************************************************
pycharm 快速导包快捷键 Alt + Enter ******************************************************
cd ~/Desktop
django-admin startproject drfdemo

使用pycharm打开项目,设置虚拟环境的解析器,并修改manage.py中的后缀参数。

INSTALLED_APPS = [ ... 'rest_framework', ]
接下来就可以使用DRF提供的功能进行api接口开发了。在项目中如果使用rest_framework框架实现API接口,主要有以下三个步骤:
-
将请求的数据(如JSON格式)转换为模型类对象
-
操作数据库
-
将模型类对象转换为响应的数据(如JSON格式)
接下来简单实用drf:
创建新的app:
python manage.py startapp students
6.3.1. 创建模型操作类:
class Student(models.Model): # 模型字段 name = models.CharField(max_length=100,verbose_name="姓名") sex = models.BooleanField(default=1,verbose_name="性别") age = models.IntegerField(verbose_name="年龄") class_null = models.CharField(max_length=5,verbose_name="班级编号") description = models.TextField(max_length=1000,verbose_name="个性签名") class Meta: db_table="tb_student" verbose_name = "学生" verbose_name_plural = verbose_name
为了方便测试,所以我们可以在终端先创建一个数据库。
create database students charset=utf8;

6.3.1.1 执行数据迁移
1.把students子应用添加到INSTALL_APPS中
初始化数据库连接:
2.
import pymysql pymysql.install_as_MySQLdb()
3.settings.py配置文件中设置mysql的账号密码
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': "students", "HOST": "127.0.0.1", "PORT": 3306, "USER": "root", "PASSWORD":"123", } }
终端下,执行数据迁移。
python manage.py makemigrations
python manage.py migrate
在students应用目录中新建serializers.py用于保存该应用的序列化器。
创建一个StudentModelSerializer用于序列化与反序列化。
from rest_framework import serializers from students.models import Student class StudentModelSerializer(serializers.ModelSerializer): class Meta: model = Student fields = "__all__"
-
-
fields 指明该序列化器包含模型类中的哪些字段,'all'指明包含所有字段
在students应用的views.py中创建视图StudentViewSet,这是一个视图集合。
from rest_framework.viewsets import ModelViewSet from .models import Student from .serializers import StudentModelSerializer # Create your views here. class StudentViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer
-
-
serializer_class 指明该视图在进行序列化或反序列化时使用的序列化器
在students应用的urls.py中定义路由信息。
from . import views from rest_framework.routers import DefaultRouter # 路由列表 urlpatterns = [] router = DefaultRouter() # 可以处理视图的路由器 router.register('students', views.StudentViewSet) # 向路由器中注册视图集 urlpatterns += router.urls # 将路由器中的所以路由信息追到到django的路由列表中
最后把students子应用中的路由文件加载到总路由文件中.
from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path("stu/",include("students.urls")), ]
6.3.5. 运行测试
运行当前程序(与运行Django一样)
python manage.py runserver
在浏览器中输入网址127.0.0.1:8000/stu,可以看到DRF提供的API Web浏览页面:

此时增删查改页面已经生成。
1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能
Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。
接下来,为了方便演示序列化器的使用,我们先创建一个新的子应用sers
python manage.py startapp sers
我们已有了一个数据库模型类students/Student,我们想为这个模型类提供一个序列化器,可以定义如下:
from rest_framework import serializers
# 声明序列化器,所有的序列化器都要直接或者间接继承于 Serializer
# 其中,ModelSerializer是Serializer的子类,ModelSerializer在Serializer的基础上进行了代码简化
class StudentSerializer(serializers.Serializer):
"""学生信息序列化器"""
# 1. 需要进行数据转换的字段
id = serializers.IntegerField()
name = serializers.CharField()
age = serializers.IntegerField()
sex = serializers.BooleanField()
description = serializers.CharField()
# 2. 如果序列化器集成的是ModelSerializer,则需要声明调用的模型信息
# 3. 验证代码
# 4. 编写添加和更新模型的代码
| 字段构造方式 | |
|---|---|
| BooleanField | BooleanField() |
| NullBooleanField | NullBooleanField() |
| CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
| EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
| RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
| SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+ |
| URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
| UUIDField | UUIDField(format='hex_verbose') format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" |
| IPAddressField | IPAddressField(protocol='both', unpack_ipv4=False, **options) |
| IntegerField | IntegerField(max_value=None, min_value=None) |
| FloatField | FloatField(max_value=None, min_value=None) |
| DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
| DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
| DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
| TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
| DurationField | DurationField() |
| ChoiceField | ChoiceField(choices) choices与Django的用法相同 |
| MultipleChoiceField | MultipleChoiceField(choices) |
| FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| ListField | ListField(child=, min_length=None, max_length=None) |
| DictField | DictField(child=) |
| 作用 | |
|---|---|
| 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的构造方法为:
Serializer(instance=None, data=empty, **kwarg)
说明:
1)用于序列化时,将模型类对象传入instance参数
2)用于反序列化时,将要被反序列化的数据传入data参数
3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如
serializer = AccountSerializer(account, context={'request': request})
通过context参数附加的数据,可以通过Serializer对象的context属性获取。
-
-
序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时把使用的数据传递过来。
-
序列化器的字段声明类似于我们前面使用过的表单系统。
-
开发restful api时,序列化器会帮我们把模型数据转换成字典.
-
drf提供的视图会帮我们把字典转换成json,或者把客户端发送过来的数据转换字典.
序列化器的使用分两个阶段:
-
在客户端请求时,使用序列化器可以完成对数据的反序列化。
-
在服务器响应时,使用序列化器可以完成对数据的序列化。
7.3.1 序列化
7.3.1.1 基本使用
1) 先查询出一个学生对象
from students.models import Student student = Student.objects.get(id=3)
2) 构造序列化器对象
from .serializers import StudentSerializer serializer = StudentSerializer(instance=student)
3)获取序列化数据
通过data属性可以获取序列化后的数据
serializer.data # {'id': 4, 'name': '小张', 'age': 18, 'sex': True, 'description': '猴赛雷'}
完整视图代码:
from django.views import View
from students.models import Student
from .serializers import StudentSerializer
from django.http.response import JsonResponse
class StudentsView(View):
"""使用序列化器序列化转换多个模型数据"""
def get(self,request):
# 获取数据
student_list = Student.objects.all()
# 转换数据[序列化过程]
# 如果转换多个模型对象数据,则需要加上many=True
serializer = StudentSerializer(instance=student_list,many=True)
print( serializer.data ) # 序列化器转换后的数据
# 响应数据给客户端
# 返回的json数据,如果是列表,则需要声明safe=False
return JsonResponse(serializer.data,safe=False)
class StudentView(View):
"""使用序列化器序列化转换单个模型数据"""
def get(self,request,pk):
# 获取数据
student = Student.objects.get(pk=pk)
# 数据转换[序列化过程]
serializer = StudentSerializer(instance=student)
print(serializer.data)
# 响应数据
return JsonResponse(serializer.data)
定义子路由,urls.py:
from django.urls.conf import path,re_path from . import views urlpatterns = [ path(r"students/",views.StudentsView.as_view()), re_path(r"students/(?P<pk>\d+)/",views.StudentView.as_view()), ]
添加总路由
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('stu/',include(('students.urls'))),
path("ser/",include("sers.urls")),
]

浙公网安备 33010602011771号