FastAPI Web开发入门、进阶与实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.3 简单项目介绍

前面已经把项目需要的依赖包安装好了,项目的目录结构如图2-25所示。

图2-25 项目的目录结构

项目目录说明如下。

❑static:存放HTML模板的静态资源文件。

❍assets:存放HTML模板中使用的图片资源。

❍css:存放HTML模板中使用的CSS样式文件资源。

❍js:存放HTML模板中使用的JS相关的脚本文件资源。

❑templates:存放具体的HTML模板文件。其中的index.html是要渲染的具体的HTML文件。

❑main.py:应用程序启动入口文件。

2.3.1 创建app实例对象

main.py文件是应用程序服务启动入口文件,所以需要在里面实例化一个FastAPI的app实例对象,它是对整个应用程序服务的对象封装。该文件的代码如下。

上述代码说明:

❑第1行:表示从当前“PATH环境变量”中查找Python解释器的位置。为了节省篇幅,后续类似这样的默认设置不再重复展示。

❑第2行:定义当前源文件的编码方式。为了节省篇幅,后续类似这样的默认设置都不再重复展示。

❑第3行:从当前项目所处的解析器中导入之前安装的FastAPI依赖包,并从FastAPI包导入一个FastAPI类,FastAPI类是当前整个应用程序的描述。

❑第4行:导入一个类型提示模块,用于描述参数类型声明。

❑第5行:通过实例化FastAPI类得到一个应用程序实例对象,并将其命名为app对象,它代表当前程序进程的一个实例。其中,对应的参数主要用于交互式API文档信息的配置。

2.3.2 添加API请求路由注册

路由注册与Flask框架所提供的路由注册的本质是一样的。所谓路由注册,就是提供一个对应的URL地址来关联或绑定定义的函数。在常见的Web框架中,通常使用装饰器的形式对需要绑定的函数进行映射绑定,这个过程就是路由注册,也可以理解为创建视图的过程。以下示例在2.3.1小节给出的代码的基础示例上新增了相关的路由注册,具体如下。下面的代码基于app实例对象提供的装饰器实现了路由注册功能。

上述代码示例定义了一个app_hello()函数,然后通过@app.get()这个装饰器进行装饰,从而创建一个API端点路由请求。该装饰器表示当前API只能使用GET请求方式进行请求处理。@app.get("/app/hello", tags=['app实例对象注册接口—示例'])方法中的“/app/hello”参数表示请求访问URL路径地址,tags参数则表示这个API归属于“app实例对象注册接口—示例”这个分组标签下,它的主要作用是进行API分组归类,并显示在可视化交互API文档中。

当通过浏览器进行访问,并使用GET方式请求“/app/hello”这个URL时,就会触发app_hello()函数的调用,并返回函数处理结果。

注意

被@app.get()装饰的函数可以有两种,一种是使用def定义的同步函数,另一种是使用async def定义的协程函数。同步函数会运行于外部的线程池中,协程函数会运行于异步事件循环中。简单地说,同步函数是基于多线程并发模式进行相关处理的,而协程函数是基于单线程内的异步并发模式进行相关处理的。

2.3.3 添加后端渲染模板路由

对于一些应用来说,可能还需要使用后端渲染模板来展示前端页面。这里新增一个API端点路由来展示如何使用FastAPI来展示渲染HTML模板的页面。后端渲染模板有别于前后端分类开发模式,后端渲染模板会整合HTML到FastAPI服务中,而在前后端分离的项目中,FastAPI仅提供了API,前端页面通过访问API进行调用。

这里在项目目录中定义了一个templates文件夹,里面有一个index.html文件,该文件主要用于显示HTML渲染模板中的内容,文件完整代码如下:

定义好要显示在页面中的内容之后,就要定义API端点路由了,回到main.py文件中,与此相关的代码如下:

上述代码引入了渲染模板所需的模块,包括HTMLResponse、Jinja2Templates和StaticFiles,这些都是必须要有的。另外需要注意的是,在定义对应的模板渲染之前,需要挂载静态资源文件目录,只有完成挂载操作,在相关的模板中引入的静态资源才可以被正常访问。由于后端渲染模板相关知识已超出本书的范围,所以这里不再展开,有兴趣的读者可以参阅其他资料进行学习。

2.3.4 启动服务运行

至此,示例项目就创建完成了,相关的API端点路由及页面渲染都已经备齐,接下来就可以启动服务进行访问了。在启动服务之前,需要了解服务的启动方式。在本地的开发环境中,通常直接使用uvicorn进行服务启动,若是在生产环境中,则需要借助gunicorn进行部署,后文会对线上的生产环境进行详细介绍。本小节重点介绍本地开发环境中的服务启动。

在本地开发环境中,使用uvicorn启动服务分两种方式:

❑使用命令行方式启动。

❑导入uvicorn模块,使用代码方式启动。

1.使用命令行方式启动服务

首先打开Terminal会话窗口并切换到D:\fastapi_tutorial\chapter02\目录下,然后输入如下命令:

上面的命令主要是通过命令行调用uvicorn库并传入指定的参数“main:app--reload”来启动对应main模块的app对象。

上述代码中,--reload命令主要用于热启动,这个参数的主要作用是在编写代码阶段,若需要对当前代码进行改动,那么代码改动完后程序会自动重启服务的进程,使修改即时生效,这样可以提高编码效率。注意,--reload仅用于项目编码调试阶段,正式部署到生产环境后应尽量避免使用该参数。

此时,控制台输出的信息如图2-26所示。

图2-26 控制台输出的信息(一)

从图2-26可以看出,服务已经运行在地址为127.0.0.1(回环地址)的主机上,使用的端口号是8000,使用的ASGI服务容器是uvicorn。

如果希望对外允许访问服务,那么可以将--host参数设置为0.0.0.0。如果希望自定义监听端口,那么可以添加--port参数。对外允许访问设置成功后,服务所在的局域网内的所有人都可以通过访问内网分配的端口(IP+8000)或自定义的端口来访问服务。设置完成后用如下命令启动服务:

服务启动后,控制台输出的信息如图2-27所示。

图2-27 控制台输出的信息(二)

此时可以查看自己的计算机被分配到的内网IP地址。在控制台中输入查看IP的命令ipconfig,会显示图2-28所示的结果。

图2-28 查看内网IP地址

由图2-28可知,本示例中,计算机的IP地址为192.168.31.37(不同的计算机可能不一样),此时可以通过浏览器访问http://192.168.31.37:8888/得到HTML中渲染的模板内容,如图2-29所示。

图2-29 HTML中渲染的模板内容

如果想通过域名来访问API,则可以配置本地的Host进行对应的域名和IP地址映射。当然,这种方式仅限于本地测试,在真实的线上生成环境中进行域名映射需要指向公网的IP地址。

图2-30所示为使用SwitchHosts工具来修改本地计算机Host的域名映射结果。

图2-30 使用SwitchHosts工具修改本地计算机Host的域名映射结果

配置完成后,使用浏览器再次访问http://www.zyx.com:8888/,发现可以得到与之前一样的结果。

host参数主要用于绑定服务Host的IP地址,这里所说的IP地址指的是计算机主机的请求地址,通常这个地址分为公网IP地址和内网IP地址。服务采用默认配置启动时绑定的是当前的内网IP地址,上面采用的127.0.0.1是一个回环地址,也可以认为127.0.0.1和localhost是等价的。值得注意的是,localhost是一个域名,这个域名指向的IP地址是127.0.0.1。

下面对几个IP地址相关的概念进行简单介绍。

❑公网IP地址:互联网上的所有人都可以通过这个IP地址访问到服务。公网IP地址一般需要向服务提供商申请获得,如在阿里云购买云服务器时通常会配备一个公网IP地址。

❑内网IP地址:主要是指个人计算机内的局域网地址。如果服务是通过内网IP开启的,则通常只能使用本机上或所属局域网内其他内网的IP地址进行访问,外部人员是无法通过内网IP地址进行访问的。

❑0.0.0.0:代表本机上所有的IP地址,也包括了回环地址127.0.0.1。如果本机存在多网卡的情况,则0.0.0.0是所有网卡IP的集合。如果使用host=0.0.0.0绑定了IP地址,那么表示服务进程会接收来自所有网卡上的IP地址的请求。此时如果本机的防火墙关闭或开启相关允许机制,则当前局域网内的其他人也可以通过访问本机的IP地址的形式请求到接口服务。

2.使用代码方式启动服务

这里介绍的启动方式是,在main.py中导入uvicorn模块,然后使用uvicorn.run()函数来启动服务,具体的代码如下:

对于上述代码,当代码模块在当前文件夹内直接运行时,if __name__=='__main__':以下的代码块将被运行。如果代码模块是被导入的,那么if __name__=='__main__':以下的代码块不会被运行。其中,uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True)等同于使用命令行方式启动服务。

上述代码中app参数默认有3种类型:

❑可以是ASGIApplication的一个实例对象。在上面的代码中,FastAPI实例化后的app对象就是一个ASGIApplication实例对象。

❑可以是一个可调用的对象。

❑可以是一个字符串,但是这里的字符串类型必须是使用代码方式启动服务时所用的“模块名称+app对象名”,只有这样才可以找到模块下对应的ASGIApplication实例的app对象。

在使用代码方式启动服务时,如果通过app参数直接传递ASGIApplication的一个实例的对象代码如下:

那么会出现如下告警异常提示信息:

上述提示信息的意思是,如果要开启热启动或使用多进程的方式启动服务,则应使用与传入字符串类似的方式。此时可对代码进行如下修改,之后就可以正常启动服务了。

运行上述代码,在main.py文件所在界面的空白部分单击鼠标右键,在弹出的快捷菜单中选择“Run.'main'”命令即可启动服务,服务启动后的界面如图2-31所示。

图2-31 服务启动后的界面

当服务启动完成后,此时在浏览上访问http://127.0.0.1:8000/,就可以看到浏览器返回了HTML中渲染的模板内容信息。

在main.py文件中,还可以自动获取当前模块的名称main,这样不管当前模块名称怎么变化,都可以自动进行识别。具体代码如下:

有了上面的代码,再使用uvicorn.run启动服务时就不需要再手写其他代码了,后续所有的启动都可以基于此完成。

2.3.5 uvicorn参数说明

使用uvicorn这个ASGI服务器来启动服务时,可以传入的参数非常多。这里列举几个常用的参数,如表2-1所示。

表2-1 uvicorn参数及说明

(续)

uvicorn提供的参数比较多,这里不可能逐一展开介绍,更多内容可以访问uvicorn的官网来学习:https://www.uvicorn.org/。

2.3.6 查看交互式API文档

FastAPI框架的优越特性还表现在服务启动后可以直接查看自己编写的API文档。FastAPI提供了两种可视化交互式API文档模式——Swagger UI、ReDoc。

Swagger UI:它是一个流行的开源项目,可以为API自动生成交互式文档。Swagger UI允许人们通过用户界面来测试和交互式地调用API路由。

ReDoc:它是另一个流行的开源项目,提供了一个响应式的文档查看器。类似于Swagger UI,ReDoc可以帮助用户快速地浏览、测试和理解API路由的工作方式。

Swagger UI模式下,服务启动之后,通过浏览器访问http://127.0.0.1:8000/docs#/可以看到图2-32所示的结果。

图2-32 Swagger UI模式下服务启动后的界面

ReDoc模式下,服务启动之后,通过浏览器访问http://127.0.0.1:8000/redoc可以看到图2-33所示的结果。

图2-33 ReDoc模式下服务启动后的界面

通过交互式API文档可以看到,FastAPI框架会自动列举app中所有定义的API端点路由信息,此时还可以通过单击API交互文档对应的接口进行访问。

如图2-34所示,使用第一种交互式API文档,单击“Execute”按钮之后,会自动请求到后端定义的“/app/hello”请求接口。此时,接口会返回响应的数据报文内容信息。

图2-34 示例结果图