DRF (学习第一部)
目录
Web应用模式
在开发web应用中,有俩种应用模式:
1. 前后端不分离( 客户端看到的内容和所有界面效果都是由服务器提供的 )
这种情况下前端页面中会出现很多涉及到服务端的模板语法
2. 前后端分离( 把前端的界面效果(html 陈述事实就是 分离到另一个项目中, python服务端只需要返回数据即可)
前端形成一个独立的网站,服务端构成一个独立的网站.
django,一般是做web网站,如果可利用django实现前后端分离,则django就可以完成地铁站的运营调度系统,路由的终端系统,pos机的服务端系统,游戏的服务端后台,软件服务端后台.
API接口
为了在团队内部形成共识,防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种'规范能够让后端写的接口,用途一目了然,减少成本.
目前市面上大部分公司开发人员使用的接口服务框架主要有:restful rpc soap
rpc:翻译成中文:远程过程调用(远程服务调用)
服务端提供单一的请求数据的api地址:http://api.renran.cn/
post 请求
action=get_all_student&class=301&sex=1
特点:
优点:不需要在意当前操作是什么http请求,也不需要操作url地址的编写,对接简单.
缺点: 接口多了,对应的函数名和参数就多了,前端在请求api接口是,就会比较困难,也容易出现重复的接口.
restful:翻译成中文:资源状态转换
把后端的所有的数据/文件都看成资源.
那么接口请求数据,本质上来说就是对资源的操作.
web项目中操作资源,就是增删改查,所以要求在地址栏中声明要操作的资源是什么,然后通过http请求动词来说明对资源进行那种一种操作.
POST http://www.renran.cn/api/students/ 添加学生数据
GET http://www.renran.cn/api/students/ 获取所有学生
DELETE http://www.renran.cn/api/students/<pk>/ 删除id=pk的一个学生
PUT http://www.renran.cn/api/students/<pk>/ 修改一个学生的全部信息 [id,name,sex,age,]
PATCH http://www.renran.cn/api/students/<pk>/ 修改一个学生的部分信息[age]
特点:
优点: 维护开发简单, 可以保证后期的开发不会出现太多重复接口.
缺点: 有部分接口不会明确的增删改查这种区分的,所以会出现一些不伦不类的接口.会因为这些语语意不明的接口,导致后期产生过高的维护成本.
因为restful 把对资源的操作都理解成了曾删改查,建议使用http,所以restful 接口天生局限于web开发.
RESTful API 规范
REST全称是Representaional State Transfer 中文的意思是表述(编者注:通常译作为表征) 性状态转移.它首次出现在2000年roy Fielding的博士论文中
RESTful是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中。
这种风格的理念认为后端开发任务就是提供数据的,对外提供的是数据资源的访问接口,所以在定义接口时,客户端访问的URL路径就表示这种要操作的数据资源。
而对于数据资源分别使用POST、DELETE、GET、UPDATE等请求动作来表达对数据的增删查改。
请求方法 | 请求地址 | 后端操作 |
---|---|---|
GET | /students | 获取所有学生 |
POST | /students | 增加学生 |
GET | /students/<pk> | 获取主键为pk的学生 |
PUT | /students/<pk> | 修改主键为pk的学生 |
DELETE | /students/<pk> | 删除主键为pk的学生 |
事实上,我们可以使用任何一个框架都可以实现符合restful规范的API接口
参考文档::http://www.runoob.com/w3cnote/restful-architecture.html
接口实时过程中.存在幂等性.所谓幂等性是指代客户端发起多次请求是否对服务端里面的资源产生不同结果.如果多次请求,服务端的结果都是一样的,则属于幂等接口.反之则不属于幂等接口. 在http请求get/put/patch/delete都属于幂等性接口,post属于非幂等接口。
为什么要考虑幂等性?主要就是接口操作的安全性问题。
delete /api/students/1
get /api/students/
post /api/students/
序列化
api接口开发,是核心最常见的一个过程就是序列化,所谓序列化就是把 数据转格式 ,序列化可以分为俩个阶段: 序列化 和反序列化
序列化: 把我们可以识别的数据转换成指定的格式提供给别人.
例如: 我们在django中获取到的数据默认是模型对象,但是模型对象数据无法直接提供给前端或别的平台使用.所以我们需要把数据进行序列化,变成字符串或者json数据,提供给前端或者其他平台.
反序列化: 被别人提供的数据转换/还原成我们需要的格式.
例如: 前端js提供过来的json数据,对于python而言就是字符串,我们需要 进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中.
Django Rest_Framework
核心思想:缩减编写api接口的代码
djangoREST framework 是一个建立在Django基础之上的web 应用开发框架,本质上就是一个内置在django 里面的子应用,可以快速的开发REST API接口应用.
在REST framework中, 提供了序列化器对象Serialzier的定义, 可以帮助我们简化序列化与反序列化的过程,不仅如此,还提供了丰富的类视图,扩展类,视图集来简化视图的编写工作.RESTframework 还提供了认证, 权限, 限流 , 过滤 , 分页, 接口文档等功能支持.REST framework 提供了一个用于测试API接口的可视化web界面( 可以浏览器直接访问接口吗drf的api
接口测试页面非常美观)
中文文档:https://q1mi.github.io/Django-REST-framework-documentation/#django-rest-framework
github: https://github.com/encode/django-rest-framework/tree/master
特点:
- 提供了定义序列化器Serializer的方法,可以快速根据DjangoORM 或者其他库自动序列化./反序列化
- 提供了丰富的类视图 ,Mixin扩展类., 简化视图的编写.
- 丰富的定制层级:函数视图,类视图,视图集合到自动生成APi ,满足各种需要.
- 各种身份认证和权限认证方式的支持: jwt json web token)
- 内置了限流系统
- 直观的ApI web 界面:( 方便调试开发api接口)
- 可扩展性 , 插件丰富.
环境安装预与配置
DRF 需要依赖:
Python(2.7,3.2 以上)
django(1.10,1.11,2.0 以上)
DRF是以Django扩展应用的方式提供的,所以我们可以直接利用已有的django环境而无需从新创建,(若没有django环境,需要先创建环境安装Django)
安装DRF
前提是安装可django,建议安装在虚拟环境
windows的复制在linux终端是无效的,在ububtu终端下粘贴的快捷键是 shift+insert
# mkvirtualenv drfdemo -p python3
# pip install django==2.2.0 -i https://pypi.douban.com/simple pip install djangorestframework -i https://pypi.douban.com/simple # 因为我们需要接下来,需要开发api接口肯定要操作数据,所以安装pymysql
pip install pymysql -i https://pypi.douban.com/simple
linux对的终端下粘贴内容快捷键: shift+insert
创建Django项目
cd ~/Desktop
django-admin startproject drfdemo
pycharm打开项目,设置虚拟环境的解释器,
使用pycharm打开项目, 设置虚拟环境的解释器,并修改manage.py中的后缀参数>
添加rest_framework应用
在settings.py的INSTALLEN_APPS中添加rest_framework
INSTALLED_APPS = [
...
'rest_framework',
]
接下来就可以使用DRF提供的功能进行api接口开发了. 在项目中如果使用rest_framework
框架实现API接口,主要有以下三步骤:
- 将请求的数据( 如json 格式) 转换为模型类对象
- 通过模型类对象进行数据库操作, 完成客户端请求的曾删改查
- 将模型类对象装换为响应的数据( 如json格式)
体验drf完全简写代码的过程 ( 加油 )
创建子应用
# 项目根目录下创建子应用,用于展示当前例子。 python manage.py startapp students
创建模型操作类
子应用的models.py文件中创建模型对象.
from django.db import models # Create your models here.
class Student(models.Model):
# 表字段声明
# 字段名=models.数据类型(字段约束)
name = models.CharField(null=False, max_length=32, verbose_name="姓名")
sex = models.BooleanField(default=True, verbose_name="性别")
age = models.IntegerField(verbose_name="年龄")
class_num = models.CharField(max_length=5, verbose_name="班级编号")
description = models.TextField(max_length=1000, verbose_name="个性签名") # 表信息
class Meta:
# 设置表名
db_table="tb_students"
verbose_name="学生"
verbose_name_plural=verbose_name # 模型的操作方法
def __str__(self):
return self.name
为了方便测试,我们可以先创建一个数据库.
create database students charset=utf8;
执行数据迁移
把students子应用添加到ISTALLL_APPS中
初始化数据库连接
安装pymysql
pip install pymysql
主引用__init__.py 设置使用pymysql作为数据库驱动
import pymysql pymysql.install_as_MySQLdb()
settings.py 配置文件中设置mysql的账号密码
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# },
'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
错误列表
# 执行数据迁移 python manage.py makemigrations 报错如下:
解决方案:
注释掉 backends/mysql/base.py中的35和36行代码。
# 执行数据迁移发生以下错误:
解决方案:
backends/mysql/operations.py146行里面把decode换成encode:
创建序列化器
在students应用目录中新建serizlizers.py用于保存该应用的序列化器.
创建一个StudebtModelSerializer 用于序列化与反序列化
# 创建序列化器类,回头会在试图中被调用
from rest_framework import serializers
from .models import Student
class StudentModelSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = "__all__"
model指明该序列化器处理的数据字段从模型类Bookinfo参数生成
fields 之明该序列化器包含模型类中的那些字段,all 指明包含所有字段
编写视图
在students应用的views.py中创建视图
StudentsViewSet, 这是一个视图集合.
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
queryset指明该视图集在查询数据时使用的查询集
serializer_class 指明该视图在进行序列化或反序列化时使用的序列化器
定义路由
在输入端问题是应用的 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("student/",include("students.urls")),
]
运行测试
运行当前程序( 与运行Django一样)
python manage.py runserver
在浏览器中输入网址127.0.0.1:8000,可以看到DRF提供的API Web浏览页面:
1 ) 点击链接27.0.0.1:8000/stu/students 可以访问获取所有数据的接口,呈现如下页面:
2 ) 在页面底下表单部分填写学生信息, 可以访问添加新学生的接口 保存学生信息:
点击POST后, 返回如下页面信息:
3 ) 在浏览器中输入网址127.0.0.1:8000/stu/students/5/,可以访问获取单一学生信息的接口(id为5的学生),呈现如下页面:
4 ) 在页面底部表单中填写学生信息, 可以反问修改学生的接口:
点击PUT ,返回如下页面信息:
5 ) 点击DELETE按钮, 可以访问删除学生的接口:
返回, 如下页面:
序列化器 -Serializer
作用:
1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能
定义序列化器
Django REST framework中的Serializer 使用类来定义, 必须继承自rest_framework.serializers.Serializer。
接下来,为了方便演示序列化器的使用,我们先创建一个新的子应用sers
python manage.py startapp sers
我们有了一个数据库模型类students/Student
from django.db import models # Create your models here.
class Student(models.Model):
# 模型字段
name = models.CharField(max_length=100,verbose_name="姓名",help_text="提示文本:账号不能为空!")
sex = models.BooleanField(default=True,verbose_name="性别")
age = models.IntegerField(verbose_name="年龄")
class_null = models.CharField(max_length=5,verbose_name="班级编号")
description = models.TextField(verbose_name="个性签名") class Meta:
db_table="tb_student"
verbose_name = "学生"
verbose_name_plural = verbose_name
我们想为这个模型类提供一个序列化器. 可以定义如下
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. 编写添加和更新模型的代码
注意:serializer不是只能为数据库模型来定义,也可以为非数据模型类的数据定义. serializer 是独立于数据库之外的存在.
常用字段 类型:
字段 | 字段构造方式 |
---|---|
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的构造方法为:
Serializer(instance=None, data=empty, **kwarg)
说明:
- 用于序列化时,将模型类对象传入instance参数
- 用于反序列化时, 将要被反序列化的数据传入data 参数
- 除了instance和data参数外, 在构造Serializer对象时,还可以通过conrext参数额外添加数据 如
serializer = AccountSerializer(account, context={'request': request})
通过context参数附加的数据, 可以通过Serializer对象的context属性获取,
1 使用序列化器的时候一定要注意,序列化器声明了以后,不会自动执行,需要在视图中进行调用才可以.
2 序列化器无法直接接收数据, 需要在视图中创建序列化对象时使用的数据传递过来.
3 序列化器的字段声明类似于前面使用过的表单系统.
4 开发restful Api时 , 序列化器会帮我们把模型数据转换成字典.
5 drf提供的视图会帮我们把字典转换成json,或者把客户端发送过来的数据转换字典.
序列化器的使用
序列化器的使用分为俩个阶段:
- 在客户端请求时,使用序列化器可以完成对数据的反序列化.
- 在服务器响应时.使用序列化器可以完成对数据的序列化
序列化
基本使用:
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 StudentView(View):
"""使用序列化器序列化转换单个模型数据"""
def get(self,request,pk):
# 获取数据
student = Student.objects.get(pk=pk)
# 数据转换[序列化过程]
serializer = StudentSerializer(instance=student)
print(serializer.data)
# 响应数据
return JsonResponse(serializer.data)
4 )如果被序列化的是包含多条数据的查询集
QuerySet , 可以通过添加 many=True 参数补充说明
"""使用序列化器序列化转换多个模型数据"""
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) # 访问结果:
# [OrderedDict([('id', 1), ('name', 'xiaoming'), ('age', 20), ('sex', True), ('description', '测试')]), OrderedDict([('id', 2), ('name', 'xiaohui'), ('age', 22), ('sex', True), ('description', '后面来的测试')]), OrderedDict([('id', 4), ('name', '小张'), ('age', 18), ('sex', True), ('description', '猴赛雷')])]
反序列化
数据验证
- 使用序列化器进行反序列化时. 需要对数据进行验证后, 才能获取成功的数据或保存成模型类对象.
- 在获取反序列化的数据前, 必须调用Is_valid( 方法进行验证, 验证成功返回True 否则返回False.
- 验证失败,可以通过序列化器对象的errors 属性获取错误信息, 返回字典, 包含了字段的错误.如果是非字段错误,可以通过修改RESTframework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名.
- 验证成功, 可以通过序列化器对象的validated_data属性获取数据.
- 在定义序列化器时,指明每个字段的序列化类型和选项参数. 本身就是一种验证行为.
- 如我们前面定义过的BookInfoSerializer
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)
通过构造序列化器对象,并将要反序列化的数据传递给data 构造参数, 从而进行验证
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()方法还可以在验证失败时抛出异常
Serializer.ValidationError. 可以通过传递raise_exception=True参数开启吗REST framework接收到此异常, 会向前端返回HTTP400 BadRequest 响应.
# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True)
如果觉得这些都不够需要再补充定义验证行为, 可以使用以下三种方法:
! ) validate_字段名
对 <field_name>字段进行验证
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
... def validate_btitle(self, value):
if 'django' not in value.lower():
raise serializers.ValidationError("图书不是关于Django的")
return 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')]}
2 ) validate
在序列化器中需要同时对对多个字段进行比较验证时可以定义validate方法来验证,如
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
... def validate(self, 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')]}
3 ) validators
在字段中添加validators选项参数, 也可以补充验证行为, 如
def about_django(value):
if 'django' not in value.lower():
raise serializers.ValidationError("图书不是关于Django的") class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
btitle = serializers.CharField(label='名称', max_length=20, validators=[about_django])
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 = {'btitle': 'python'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # False
serializer.errors
# {'btitle': [ErrorDetail(string='图书不是关于Django的', code='invalid')]}
反序列化 保存数据
前面的验证数据成功后.我们可以使用序列化器来完成数据反序列化的过程, 这个过程可以把数据传成模型类对象.
可以通过实现create( 和 update( 俩个方法来实现.
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
... def create(self, validated_data):
"""新建"""
return BookInfo(**validated_data) def update(self, instance, validated_data):
"""更新,instance为要更新的对象实例"""
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.objects.create(**validated_data) def update(self, instance, validated_data):
"""更新,instance为要更新的对象实例"""
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()
return instance
实行了上述俩个方法后, 在反序列化数据的时候, 就可以通过save() 方法返回一个数据对象实例化
book = serializer.save()
如果创建序列化器对象的时候, 没有传递instance实例, 则调用save( )方法的时候吗create( 被调用, 相反, 如果传递了instance实例, 则调用save() 方法的时候,update() 被调用.
from db.serializers import BookInfoSerializer
data = {'btitle': '封神演义'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # True
serializer.save() # <BookInfo: 封神演义> from db.models import BookInfo
book = BookInfo.objects.get(id=2)
data = {'btitle': '倚天剑'}
serializer = BookInfoSerializer(book, data=data)
serializer.is_valid() # True
serializer.save() # <BookInfo: 倚天剑>
book.btitle # '倚天剑'
附加说明
1 ) 在对序列化器进行save()保存时, 可以额为传递数据, 这些数据可以在create() 和update( 中的validated_date参数获取到
# request.user 是django中记录当前登录用户的模型对象
serializer.save(owner=request.user)
2 ) 默认序列化器必须传递所有热气red的字段, 否则会抛出验证异常. 但是我们可以使用partial参数来允许部分字段更新
# Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)
模型类序列化器
1 ) 使用飞力达来明确字段, __all__ 表名包含所有字段, 也可以写明具体哪些字段,如
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date')
2 ) 使用exclude可以明确排除哪些字段
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
exclude = ('image',)
3 )显示指明字段,如:
class HeroInfoSerializer(serializers.ModelSerializer):
hbook = BookInfoSerializer() class Meta:
model = HeroInfo
fields = ('id', 'hname', 'hgender', 'hcomment', 'hbook')
4 ) 指明只读字段
可以通过read_only_fields指明只读字段, 仅用于序列化输出的字段
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
read_only_fields = ('id', 'bread', 'bcomment')
添加额外参数
可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选型参数
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
extra_kwargs = {
'bread': {'min_value': 0, 'required': True},
'bcomment': {'min_value': 0, 'required': True},
} # BookInfoSerializer():
# id = IntegerField(label='ID', read_only=True)
# btitle = CharField(label='名称', max_length=20)
# bpub_date = DateField(allow_null=True, label='发布日期', required=False)
# bread = IntegerField(label='阅读量', max_value=2147483647, min_value=0, required=True)
# bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=0, required=True)
DRF (学习第一部)的更多相关文章
- drf (学习第二部)
目录 http球球处理 请求与响应 Response 常用属性 状态码 http请求处理 drf除了在数据序列化部分简写代码之外,还在视图中提供了简写操作.所以在Django原有的Django.vie ...
- Django (学习第一部 基础操作)
django 1 django 文件相关信息 2 Python创建django 3 命令行创建django 4 Django 必会三板斧 5 静态文件配置 6 request对象方法 7 pychar ...
- oracle学习 第一章 简单的查询语句 ——03
1.1最简单的查询语句 例 1-1 SQL> select * from emp; 例 1-1 结果 这里的 * 号表示全部的列.它与在select 之后列出全部的列名是一样的.查询语句以分号( ...
- 我的第一部原创《JavaScript 全栈开发》正式上市了!
在经过了漫长的创作.审校过程之后,<JavaScript 全栈开发>终于迎来了在各大平台上正式出版的日子,以下是这本书的基本信息: 出品方: 异步社区:https://www.epubit ...
- Magento学习第一课——目录结构介绍
Magento学习第一课--目录结构介绍 一.Magento为何强大 Magento是在Zend框架基础上建立起来的,这点保证了代码的安全性及稳定性.选择Zend的原因有很多,但是最基本的是因为zen ...
- YII2学习第一天
YII2学习第一天,之前稍微看了看TP,感觉和自己的理念不是很符合,然后转学YII2了. 使用的文档是https://github.com/yiisoft/yii2/tree/master/docs/ ...
- Java学习第一天
Java学习第一天 对于网络管理员或者黑客必须知道的八个cmd命令 详情请参考:http://www.2cto.com/os/201608/533964.html nbtstat ...
- 一、Android学习第一天——环境搭建(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 一. Android学习第一天——环境搭建 Android 开发环境的搭建 ...
- web学习第一章
web学习第一章 我是大概9月10日开始走上IT之路的,一开始学习了小段时间的自动化办公软件, 昨天我开始学习客户端网页编程,我了解什么是WEB,一些比较老古董的计算模式和发展历史,印象最让我深刻 ...
- Java 学习第一步-JDK安装和Java环境变量配置
Java学习第一步——JDK安装及Java环境变量配置 [原文] 2014-05-30 9:09 Java SE 阿超 9046 views Java作为当下很主流的编程语言,学习Java的朋 ...
随机推荐
- Spark Job-Stage-Task实例理解
Spark Job-Stage-Task实例理解 基于一个word count的简单例子理解Job.Stage.Task的关系,以及各自产生的方式和对并行.分区等的联系: 相关概念 Job:Job是由 ...
- Orchard Core创建CMS/Blog站点
安装.NET Core SDK 下载并安装当前最新版本.NET Core SDK 3.1: https://dotnet.microsoft.com/download 安装visual studio ...
- Java中的常见锁(公平和非公平锁、可重入锁和不可重入锁、自旋锁、独占锁和共享锁)
公平和非公平锁 公平锁:是指多个线程按照申请的顺序来获取值.在并发环境中,每一个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个就占有锁,否者就会加入到等待队列中,以 ...
- 【MySQL】面试官:如何添加新数据库到MySQL主从复制环境?
写在前面 今天,一名读者反馈说:自己出去面试,被面试官一顿虐啊!为什么呢?因为这名读者面试的是某大厂的研发工程师,偏技术型的.所以,在面试过程中,面试官比较偏向于问技术型的问题.不过,技术终归还是要服 ...
- 每日一个知识点系列:volatile的可见性原理
每日一个知识点系列的目的是针对某一个知识点进行概括性总结,可在一分钟内完成知识点的阅读理解,此处不涉及详细的原理性解读. img 看图说话 关键点1: 总线嗅探器(MESI 缓存一致性原理 ) 关键点 ...
- spring+springmvc+mybatis+shiro
创建maven框架https://blog.csdn.net/Ajax_mt/article/details/78549119 具体下边 https://blog.csdn.net/w2222288/ ...
- Spring Boot 第三弹,一文带你了解日志如何配置?
前言 日志通常不会在需求阶段作为一个功能单独提出来,也不会在产品方案中看到它的细节.但是,这丝毫不影响它在任何一个系统中的重要的地位. 今天就来介绍一下Spring Boot中的日志如何配置. Spr ...
- nginx 1.12 HTTPS双向认证配置
使用openssl生成相关证书: #生成CA私钥,私钥会被加密,需要设置密码 openssl genrsa -aes256 -out ca.key 2048 #生成CA证书签名请求,需要输入CA私钥密 ...
- C++ “string”: 未声明的标识符
转载:https://blog.csdn.net/kkkmmmjjjj/article/details/53780549 解决方案: 要添加using namespace std;语句在宏定义后面. ...
- 《穷查理年鉴》金钱 & 生意 & 律师(关于金钱)
金钱 025.钱还得快才会借得快. 030.钱和人有着复杂的友谊:人能让钱变坏,钱也能让人变坏. 034.绝望增加债务,勤奋偿还债务. 037.只有一无所有的人才会没有烦恼. 049.穷人为他的胃找食 ...