1.Restful API接口实现
1.1需求实现思路
1、获取指定的图书信息:
1)根据pk获取指定的图书对象(pk由查询字符串的形式传给后端)
2)将图书的json数据返回,状态码:200
2、修改指定的图书信息:
1)根据pk获取指定的图书对象
2)获取参数(btitle,bpub_date)并进行校验
3)修改指定的图书的数据并更新到数据表
4)返回修改图书的json数据,状态码:200
3、删除指定的图书信息:
1)根据pk获取指定的图书对象
2)删除对应数据
3)返回响应,状态码:204
注意:
- pk是id的一个别称
- 重点掌握的是实现的思路,如何去将需求一步步实现出来,然后其次重要的就是代码。
2.明确RestAPI接口实现时的主要工作
2.1序列化&反序列化
把程序中的数据结构类型转换为其他格式的数据,这个过程叫做序列化的过程
例:将模型类对象转换为字典或者json数据的过程,就叫做序列化的过程。
把其他格式的数据转换为程序中数据结构类型,这个过程叫做反序列化的过程。
例:将前端传递的数据保存到模型对象中的过程,叫做反序列化过程。
2.2RestAPI接口核心的工作:
- 把数据库数据序列化为前端所需要的格式,并返回。
- 把前端发送的数据反序列化为模型类对象,并保存到数据库中。
3.DRF框架
作用:大大提高RestAPI接口开发效率
简介:
Django REST framework 框架是一个用于构建Web API 的强大而又灵活的工具。
通常简称为DRF框架 或 REST framework。
DRF框架是建立在Django框架基础之上,由Tom Christie大牛二次开发的开源项目。
特点:
- 提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
- 提供了丰富的类视图、Mixin扩展类,简化视图的编写;
- 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;
- 多种身份认证和权限认证方式的支持;
- 内置了限流系统;
- 直观的 API web 界面;
- 可扩展性,插件丰富
重点掌握:
序列化器、类视图、Mixin扩展类
3.1环境安装与配置
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)
3.1.1安装DRF
pip install djangorestframework
3.1.2 添加rest_framework应用
我们利用在Django框架学习中创建的demo工程,在settings.py的INSTALLED_APPS中添加’rest_framework’。
INSTALLED_APPS = [ ... 'rest_framework', ]
接下来就可以使用DRF进行开发了。
3.2见识DRF的魅力
我们仍以在学习Django框架时使用的图书英雄为案例,使用Django REST framework快速实现图书的REST API。
3.2.1. 创建序列化器
在booktest应用中新建serializers.py用于保存该应用的序列化器。
创建一个BookInfoSerializer用于序列化与反序列化。
编写图书数据序列化器类
class BookInfoSerializer(serializers.ModelSerializer): """图书数据序列化器类""" class Meta: # 指定序列化器类对应模型类 model = BookInfo # 指定需要模型类中哪些字段,__all__代表所有 fields = '__all__'
- model 指明该序列化器处理的数据字段从模型类BookInfo参考生成
- fields 指明该序列化器包含模型类中的哪些字段,’all‘指明包含所有字段
3.2.2. 编写视图
在booktest应用的views.py中创建视图BookInfoViewSet,这是一个视图集合。
from rest_framework.viewsets import ModelViewSet from booktest.serializers import BookInfoSerializer from booktest.models import BookInfo class BookInfoViewSet(ModelViewSet): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer
- queryset 指明该视图集在查询数据时使用的查询集
- serializer_class 指明该视图在进行序列化或反序列化时使用的序列化器
3.2.3. 定义路由
在booktest应用的urls.py中定义路由信息。
路由Router:动态生成视图集中API处理函数的url地址的配置项
from booktest import views from rest_framework.routers import DefaultRouter urlpatterns = [ ... ] # 路由Router:动态生成视图集中API处理函数的url地址的配置项 router = DefaultRouter() # 可以处理视图的路由器 router.register('books', views.BookInfoViewSet, name='books') # 向路由器中注册视图集 urlpatterns += router.urls # 将路由器中的所以路由信息追到到django的路由列表中
4.Serializer序列化器
作用:进行数据的序列化和反序列化
序列化:把对象转换为字典
反序列化:数据校验;数据保存(可以利用这一点实现新增和更新);
4.1使用
定义一个序列化器类
serializers.Serializer:DRF框架中所有序列化器的父类,定义序列化器类时,可以直接继承此类
serializers.ModelSerializer:是Serializer的子类,在父类基础上,添加了一些功能
序列化器类语法:字段名 = serializers.字段类型(选项参数)
from rest_framework import serializers # serializers.Serializer:DRF框架中所有序列化器的父类,定义序列化器类时,可以直接继承此类 # serializers.ModelSerializer:是Serializer的子类,在父类基础上,添加了一些功能 class 模型类(models.Model): # 字段名 = models.字段类型(选项参数) class 序列化器名(serializers.Serializer): # 字段名 = serializers.字段类型(选项参数)
4.2通用选项参数
参数名称 | 解释 |
required | 默认为True,意思是这个字段在反序列化时必须输入 |
read_only、write_only | 默认是False,如果是仅用于反序列化输出时使用,那么将write_only改为True,如果是仅用于序列化输出,将read_only改为True。 |
default | 我们在使用序列化和反序列化时使用的默认值 |
allow_null | 表明该字段是否允许传入None,默认False |
help_text、label_text | 可以理解为注释,在web直观显示的时候有一个显示信息。不重要 |
4.3创建Serializer对象
定义好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属性获取。
4.4序列化的定义
Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。
例如,我们已有了一个数据库模型类BookInfo
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)
我们想为这个模型类提供一个序列化器,可以定义如下:
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是独立于数据库之外的存在。
4.5序列化功能(重点掌握)
把实例对象转换为字典数据
知识点:
1、序列化单个对象
2、序列化多个对象
3、关联对象的嵌套序列化
1)将关联对象序列化为关联对象的主键
# 在英雄类(多)中添加 hbook = serializers.PrimaryKeyRelatedField(label='图书',read_only=True) # 在书中(一)中添加,因为书中有好多个英雄人物,想要都显示,所以要添加many这一个参数。 heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
2)使用指定的序列化器将关联对象进行序列化(字典套字典的显示方式)
hbook = BookInfoSerializer(label='图书')
3)将关联对象序列化为关联对象模型类_str_方法的返回值
hbook = serializers.StringRelatedField(label='图书')
4.6反序列化功能(重点掌握)
4.6.1数据校验
is_valid()
调用此方法进行数据校验,它会先去你定义的序列化器类中的字段中,看是否满足你的条件,然后再进行系统提供的校验。
# 调用方法进行校验,返回结果是True或者False serializer.is_valid() # 获取校验失败错误的信息 serializer.errors # 获取校验成功之后的数据 serializer.validated_data
基本的校验不能满足我们的需求,我们可以补充验证行为。有三种方式。
1)validators的使用:
先定义一个函数,设置校验过程:
def about_django(value): if 'django' not in value.lower(): raise serializers.ValidationError("图书不是关于Django的") return value
然后在字段中添加validators选项参数,写一个列表,将定义的校验函数名放进去:
btitle = serializers.CharField(label='名称', max_length=20, validators=[about_django])
2)在序列化器类里面定义一个方法:
validate_<field_name>
field_name是字段名,前面是固定的。
对<field_name>
字段进行验证,如
def validate_btitle(self,value): if 'django' not in value.lower(): raise serializers.ValidationError("图书不是关于Django的") return value
3)validate的使用:
结合多个字段内容进行校验,
attrs是serializer = BookInfoSerializer(data=data)
中的data的完整内容。
def validate(self,attrs): bread = attrs['bread'] bcomment = attrs['bcomment'] if bread < bcomment: raise serializers.ValidationError('图书的阅读量必须大于评论量') return attrs
4.6.2反序列化-数据保存
前提条件:校验通过之后,可以调用serializer.save()进行数据保存。
新增:
调用serializer.save()的时候,会调用系统的create方法,然后就会报错,我们如果想不报错,那么我们在序列化器类中重写create方法。create需要传一个参数validated_data,它是校验之后的数据(数据类型是字典)。**validated_data
是对这个字典进行拆包。
def create(self,validated_data): book = BookInfo.objects.create(**validated_data) return book
然后使用serializer.data就能获取新增图书序列化字典数据
更新:
1.获取id为1的图书
2.创建序列化器对象,要将更新的数据,传入对象
3.调用is_valid方法进行数据校验。
4.校验之后,我们就可以进行序列化-数据保存。
在序列器类中重写update方法:
def update(self,instance,validated_data): """ instance:创建序列化器对象时传入实例对象 validated_data:字典,校验之后的数据 """ btitle = validated_data.get('btitle') bpub_date = validated_data.get('bpub_date') instance.btitle = btitle instance.bpub_date = bpub_date instance.save() return instance
5.获取更对象的序列化的字典
单词补充:
implement
实现,在报错的时候出现了这个单词。遇到这个报错,我们需要重写create方法。
4.7模型类序列化ModelSerializer
如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
ModelSerializer与常规的Serializer相同,但提供了:
- 基于模型类自动生成一系列字段
- 包含默认的create()和update()的实现
class BookInfoSerializer(serializers.ModelSerializer): """图书序列化器类""" class Meta: # 指定序列化器对应模型类 model = BookInfo # 指明依据模型类的哪些字段生成序列化器类的字段,__all__代表所有 fields = '__all__'