把软件(Software)、平台(Platform)、基础设施(Infrastructure)做成服务(Service)是很多IT企业都一直在做的事情,这就是大家经常听到的SasS(软件即服务)、PasS(平台即服务)和IasS(基础设置即服务)。实现面向服务的架构(SOA)有诸多的方式,包括RPC(远程过程调用)、Web Service、REST等,在技术层面上,SOA是一种抽象的、松散耦合的粗粒度软件架构;在业务层面上,SOA的核心概念是“重用”和“互操作”,它将系统资源整合成可操作的、标准的服务,使得这些资源能够被重新组合和应用。在实现SOA的诸多方案中,REST被认为是最适合互联网应用的架构,符合REST规范的架构也经常被称作RESTful架构。
REST概述
REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的,Roy是HTTP协议(1.0和1.1版)的主要设计者、Apache服务器软件主要作者、Apache基金会第一任主席。在他的博士论文中,Roy把他对互联网软件的架构原则定名为REST,即REpresentational State Transfer的缩写,中文通常翻译为“表现层状态转移”或“表述状态转移”。
这里的“表现层”其实指的是“资源”的“表现层”。所谓资源,就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲或一种服务。我们可以用一个URI(统一资源定位符)指向资源,要获取到这个资源,访问它的URI即可,URI就是资源在互联网上的唯一标识。资源可以有多种外在表现形式。我们把资源具体呈现出来的形式,叫做它的“表现层”。比如,文本可以用text/plain
格式表现,也可以用text/html
格式、text/xml
格式、application/json
格式表现,甚至可以采用二进制格式;图片可以用image/jpeg
格式表现,也可以用image/png
格式表现。URI只代表资源的实体,不代表它的表现形式。严格地说,有些网址最后的.html
后缀名是不必要的,因为这个后缀名表示格式,属于“表现层”范畴,而URI应该只代表“资源”的位置,它的具体表现形式,应该在HTTP请求的头信息中用Accept
和Content-Type
字段指定,这两个字段才是对“表现层”的描述。
访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。Web应用通常使用HTTP作为其通信协议,客户端想要操作服务器,必须通过HTTP请求,让服务器端发生“状态转移”,而这种转移是建立在表现层之上的,所以就是“表现层状态转移”。客户端通过HTTP的动词GET、POST、PUT(或PATCH)、DELETE,分别对应对资源的四种基本操作,其中GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT(或PATCH)用来更新资源,DELETE用来删除资源。
简单的说RESTful架构就是:“每一个URI代表一种资源,客户端通过四个HTTP动词,对服务器端资源进行操作,实现资源的表现层状态转移”。
我们在设计Web应用时,如果需要向客户端提供资源,就可以使用REST风格的URI,这是实现RESTful架构的第一步。当然,真正的RESTful架构并不只是URI符合REST风格,更为重要的是“无状态”和“幂等性”两个词,我们在后面的课程中会为大家阐述这两点。下面的例子给出了一些符合REST风格的URI,供大家在设计URI时参考。
请求方法(HTTP动词) | URI | 解释 |
---|---|---|
GET | /students/ |
获取所有学生 |
POST | /students/ |
新建一个学生 |
GET | /students/ID/ |
获取指定ID的学生信息 |
PUT | /students/ID/ |
更新指定ID的学生信息(提供该学生的全部信息) |
PATCH | /students/ID/ |
更新指定ID的学生信息(提供该学生的部分信息) |
DELETE | /students/ID/ |
删除指定ID的学生信息 |
GET | /students/ID/friends/ |
列出指定ID的学生的所有朋友 |
DELETE | /students/ID/friends/ID/ |
删除指定ID的学生的指定ID的朋友 |
DRF概述
在Django项目中,如果要实现REST架构,即将网站的资源发布成REST风格的API接口,可以使用著名的三方库djangorestframework
,我们通常将其简称为DRF。
安装
pip install djangorestframework
配置
INSTALLED_APPS = [
'rest_framework',
]
# 下面的配置根据项目需要进行设置
REST_FRAMEWORK = {
# 配置默认页面大小
# 'PAGE_SIZE': 10,
# 配置默认的分页类
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
# 配置异常处理器
# 'EXCEPTION_HANDLER': '...',
# 配置默认解析器
# 'DEFAULT_PARSER_CLASSES': (
# 'rest_framework.parsers.JSONParser',
# 'rest_framework.parsers.FormParser',
# 'rest_framework.parsers.MultiPartParser',
# ),
# 配置默认限流类
# 'DEFAULT_THROTTLE_CLASSES': (
# '...'
# ),
# 配置默认授权类
# 'DEFAULT_PERMISSION_CLASSES': (
# '...',
# ),
# 配置默认认证类
# 'DEFAULT_AUTHENTICATION_CLASSES': (
# '...',
# ),
}
编写序列化器
前后端分离的开发需要后端为前端、移动端提供API数据接口,而API接口通常情况下都是返回JSON格式的数据,这就需要对模型对象进行序列化处理。DRF中封装了Serializer
类和ModelSerializer
类用于实现序列化操作,通过继承Serializer
类或ModelSerializer
类,我们可以自定义序列化器,用于将对象处理成字典,代码如下所示。
在应用下创建serializer.py文件,并添加下面的代码
class SubjectSerializer(serializers.ModelSerializer):
class Meta:
model = Subject
fields = '__all__'
编写接口(视图)函数
DRF框架支持两种实现数据接口的方式,一种是FBV(基于函数的视图),另一种是CBV(基于类的视图)。我们先看看FBV的方式如何实现数据接口,代码如下所示。
@api_view(('GET', ))
def get_test(request: HttpRequest) -> HttpResponse:
subjects = Subject.objects.all().order_by('no')
# 创建序列化器对象并指定要序列化的模型
serializer = SubjectSerializer(subjects, many=True)
# 通过序列化器的data属性获得模型对应的字典并通过创建Response对象返回JSON格式的数据
return Response(serializer.data)
@api_view(('POST',))
def post_test(request: HttpRequest) -> HttpResponse:
print(request.data)
user_name = request.data.get('userName')
pass_word = request.data.get('passWord')
return Response({"userName": user_name, "passWord": pass_word})
配置url映射
urlpatterns = [
path('api/get_test/', get_test),
path('api/post_test/', post_test),
]
访问接口地址
http://127.0.0.1:8000/vote/api/get_test/
会显示如下的页面: