The most commonly used web frameworks for building REST APIs with python is Flask and Django. Though we could build APIs with django, the real purpose of Django is building an end to end web application. On the other hand, flask is pretty light weight and can help us quickly build REST APIs. Before jumping into fastapi
let’s quickly revisit a basic flask application.
使用python构建REST API的最常用Web框架是Flask和Django。 尽管我们可以使用django构建API,但是Django的真正目的是构建端到端的Web应用程序。 另一方面,flask重量很轻,可以帮助我们快速构建REST API。 在进入fastapi
之前,让我们快速回顾一下基本的flask应用程序。
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/", methods = ["GET"])
def index():
return jsonify({"appname" :"firstapp"}),200
if __name__ == "__main__":
app.run(debug=True)
Running the above code should give the following logs and output
运行上面的代码应提供以下日志和输出
* Serving Flask app "myflaskapi" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 207-495-435
127.0.0.1 - - [25/Sep/2020 12:35:03] "GET / HTTP/1.1" 200 -Output:
{
"appname": "firstapp"
}
The fundamental problem of flask is it is based on WSGI server which is synchronous. This means that these cannot perform any non blocking asynchronous operations. For instance , consider the example below.
flask的根本问题是它基于同步的WSGI服务器。 这意味着它们不能执行任何非阻塞异步操作。 例如,请考虑以下示例。
@app.route("/", methods=["GET"])
def index():
response = requests.get(url="https://google.com")
print(response.content)
return jsonify({"content" : str(response.content)}), 200
In the above code, the response is returned only after the execution of requests.get
method. Until then, the API
is blocked and unavailable to handle further requests.
在上面的代码中,仅在执行requests.get
方法之后返回响应。 在此之前,该API
被阻止并且无法处理其他请求。
This use case is still valid with a WSGI server like gunicorn handling the requests with worker threads. Ofcourse one would argue that this could still be made asynchronous using Klein
or other libraries. But that still adds further overhead.
这种用例对于像gunicorn这样的WSGI服务器仍然有效,该服务器使用工作线程处理请求。 当然有人会说,仍然可以使用Klein
或其他库将其异步化。 但这仍然增加了额外的开销。
We also cannot use the asyncio
library with flask
apis as asyncio expects a coroutine
and flask is incompatible with a coroutine.
我们也不能将asyncio
库与flask
api一起使用,因为asyncio期望coroutine
并且flask与协程不兼容。
To get around this, we have fastapi
which is based on asyncio.
为了解决这个问题,我们有fastapi
这是基于ASYNCIO 。
介绍Fastapi (Introducing Fastapi)
FastAPI is a modern, high-performance, web framework for building APIs with Python 3.6+ based on standard Python type hints.FastAPI
is actually a sub-class of Starlette
. So, if you already know or use Starlette, most of the functionality will work the same way.Fast API claims to be one of the fastest web frameworks on par with Go
and Nodejs
.
FastAPI是一种现代的高性能Web框架,用于基于标准Python类型提示使用Python 3.6+构建API。 FastAPI
实际上是一个子类的Starlette
。 因此,如果您已经了解或使用Starlette,则大多数功能将以相同的方式工作.Fast API声称是与Go
和Nodejs
相提并论的最快的Web框架Nodejs
。
We will discuss the following basic features here:
我们将在这里讨论以下基本功能:
- A basic fastapi program 基本的fastapi程序
- How to specify path and query parameters如何指定路径和查询参数
- How to send a request body to fast api如何将请求正文发送到快速API
- Specifying form data 指定表格数据
- How to perform HTTP file upload to fast api如何执行HTTP文件上传到快速api
- Generating swagger files for APIs 生成API的swagger文件
安装快速API(Installing fast api)
pip install fastapi
We use an ASGI server to start a fastapi unlike WSGI in a flask application. The ASGI server is uvicorn.
我们在烧瓶应用程序中使用ASGI服务器来启动与WSGI不同的fastapi。 ASGI服务器是uvicorn 。
安装uvicorn (Installing uvicorn)
pip install uvicorn
Run fastapi using uvicorn
fastapi using uvicorn
运行fastapi using uvicorn
#Syntax
uvicorn <filename>:<app-name> --reloaduvicorn myapp:app --reloadOutput:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [33149] using statreload
INFO: Started server process [33151]
INFO: Waiting for application startup.
INFO: Application startup complete.
The default port of fastapi
is 8000.
fastapi
的默认端口是8000。
1.基本的fastapi程序 (1. A basic fastapi program)
Let’s quickly rewrite the basic flask
program using fastapi
让我们使用fastapi
快速重写基本的flask
程序
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def index():
return {"appname": "firstapp"}
# Calling API with http://localhost:8000
Access this using localhost:8000 and it will give the below output.
使用localhost:8000进行访问,它将给出以下输出。
Output:{"appname": "firstapp"}
Let’s quickly check the differences(or similarities) with flask
:
让我们快速检查一下flask
的差异(或相似点):
app.<http-method-name>
is used instead ofapp.route(methods=[])
.i.e For GET we say@app.get()
app.<http-method-name>
代替app.route(methods=[])
ie对于GET,我们说@app.get()
We don’t have to import
jsonify
/json
.dumps
like we do inflask
. The response is already returned asjson
. However we still haveJSONResponse
infastapi
if we have to return a customized response.我们不必导入
jsonify
/json
。 像我们在flask
一样dumps
。 该响应已作为json
。 但是,如果必须返回自定义的响应,则在fastapi
仍然有JSONResponse
。
2.指定路径参数和查询参数 (2.Specifying path parameters and query parameters)
Let’s see how to specify path and query parameters in fastapi.
让我们看看如何在fastapi中指定路径和查询参数。
from fastapi import FastAPI
app = FastAPI()
@app.get("/getuser/{username}/")
async def index(username: str, user_id: int):
return {"username": username, 'user_id': user_id}
# Calling API with http://localhost:8000/getuser/defaultuser?user_id=123
Output:
{
"username": "defaultuser",
"user_id": "123"
}
Output:{"username": "defaultuser",
"user_id" : "123"
}
There is a little addition here which you may or may not be familiar with. We have declared a type hint
for the username path parameter to specify that it is of type str
. To know more about type hints
kindly check my other article here.
这里可能有您可能不熟悉的一些附加内容。 我们已经为用户名path参数声明了type hint
,以指定它的类型为str
。 要了解有关type hints
更多信息,请在此处查看我的其他文章。
Any arguments declared that are not as part of the url path will automatically be considered as query parameters. In the above code, user_id
is a query parameter and username is a path parameter.
声明的不属于url路径的任何参数将自动被视为查询参数。 在上面的代码中, user_id
是一个查询参数,而username是一个路径参数。
Failing to provide any required query parameters will throw an error like so.
未能提供任何必需的查询参数将引发类似的错误。
缺少字段参数时出错 (Error for missing fields parameter)
{
"detail": [{
"loc": [
"query",
"user_id"
],
"msg": "field required",
"type": "value_error.missing"
}]}
3.指定请求正文 (3. Specifying request body)
To send a request body, we have to use pydantic
models. Pydantic models define a blueprint for your request body and their types. For more details on pydantic check here.
要发送请求正文,我们必须使用pydantic
模型。 Pydantic模型为您的请求主体及其类型定义了一个蓝图。 有关pydantic的更多详细信息,请点击此处。
from pydantic import BaseModel
class Basic(BaseModel):
username : str
userid : int
designation : str
pay : float
# We are just returning the request body as a response
@app.post("/user/createuser", status_code=201)
async def create_user(user: Basic):
return user
The request body is automatically read as json
and we don’t have to use request.json()
as we do in flask.The http
status codes can be specified as part of the decorator.
请求主体会自动读取为json
而我们不必像在flask中那样使用request.json()
。 http
状态代码可以指定为装饰器的一部分。
We could also use default variables for status codes specified in fastapi
as shown below.
我们还可以将默认变量用于在fastapi
指定的状态代码,如下所示。
from fastapi import FastAPI, status
# We are just returning the request body as a response
# Note the status code imported from status module
@app.post("/user/createuser", status_code=status.HTTP_201_CREATED)
async def create_user(user: Basic):
return user
4.指定表格数据(4. Specifying Form Data)
Using form data requires installing python-multipart
module.
使用表单数据需要安装python-multipart
模块。
pip install python-multipart
After installing multi-part library, add form data as shown below
安装多部分库后,如下所示添加表单数据
from fastapi import FastAPI,Form
@app.post("/user/createuser", status_code=status.HTTP_201_CREATED)
async def create_user(username: str = Form(...), password: str = Form(..., min_length=8)):
return username
In the above code username and password are mandatory form data to be sent as part of the POST
request. If you are wondering about the ...
(ellipsis) in the Form
object, it is used to specify that they are mandatory arguments when using a Form()
object.
在上面的代码中,用户名和密码是必填表格数据,将作为POST
请求的一部分发送。 如果您想知道Form
对象中的...
(省略号),则可以在使用Form()
对象时将其指定为必需参数。
This is a convention across fastapi
functions to specify mandatory parameters without mentioning default values.
这是fastapi
函数之间的约定,用于指定必需参数而不提及默认值。
The first parameter of the Form
function is the default
parameter which is None
here because it is not necessary.
Form
函数的第一个参数是default
参数,此处为None
,因为它不是必需的。
@app.post("/user/createuser", status_code=status.HTTP_201_CREATED)
async def create_user(username: str = Form(default=None), password: str = Form(default=None, min_length=5))):
return username
Specifying None like above, makes username and password fields optional and the API will work even if the consumer does not send the username and password fields.
如上所述指定None,则使用户名和密码字段为可选,即使使用者未发送用户名和密码字段,API也将起作用。
However, we want to mandate the user to pass username and password fields as part form data.
但是,我们希望授权用户传递用户名和密码字段作为表单数据的一部分。
That’s why we have to set the default positional argument to ...
ellipsis which ensures we don’t have default values for arguments and also mandate the username/password arguments.
这就是为什么我们必须将默认位置参数设置为...
省略号,以确保我们没有参数的默认值,并且还必须强制使用用户名/密码参数。
Similar to Form data, Path parameters and Query parameters as well can be specified as shown above.
与表单数据类似,也可以如上所述指定Path参数和Query参数。
5.上传文件 (5. Uploading Files)
Files can be uploaded via HTTP using File
and UploadFile in fastapi.
The response returned here is a message and the uploaded filetype
可以使用UploadFile in fastapi.
File
和UploadFile in fastapi.
通过HTTP上传File
UploadFile in fastapi.
此处返回的响应是一条消息和上传的文件类型
from fastapi import FastAPI, File, UploadFile
@app.post("/files/uploadfile", status_code=status.HTTP_201_CREATED)
async def upload_file(file: UploadFile = File(...)):
return {"message": " Valid file uploaded", "filetype": file.content_type}
# Uploading a pdf file
# API : http://localhost:8000/files/uploadfile
Output:{"message": " Valid file uploaded",
"filetype": "application/pdf"}
6.自动生成的Swagger API: (6. Auto generated Swagger APIs:)
This is my personal favourite feature of fastapi. The most annoying thing about being a developer is documenting the APIs in a swagger file in our busy schedule. Well we all hate it , don’t we? fastapi provides a brilliant auto doc generation feature for our APIs based on openAPI standards.
这是我最喜欢的fastapi功能。 成为开发人员最烦人的事情是,在我们繁忙的日程中将API记录在庞大的文件中。 好吧,我们都讨厌它,不是吗? fastapi为我们的基于openAPI标准的API提供了出色的自动文档生成功能。
For all the routes written, the swagger file will be available in the following route.
对于所有写入的路由,swagger文件将在以下路由中可用。
http://localhost:8000/docs
This is a screenshot from our swagger file listing one of the GET APIs.
这是我们的庞大文件的屏幕截图,其中列出了GET API之一。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/4fd7f37abe6f331589a266500a6bc615.png)
Summary:
概要:
- Fast API is used for asynchronous non blocking API programming. 快速API用于异步非阻塞API编程。
- FastApi claims to be the one of the fastest web frameworks for python on par with Go and Nodejs FastApi声称是与Go和Nodejs相当的最快的python Web框架之一
- An ASGI server is used to run fastapiASGI服务器用于运行fastapi
- Automatically constructs the swagger file with open-id standards 使用开放ID标准自动构建swagger文件
- The default port on which uvicorn runs is 8000.运行uvicorn的默认端口是8000。
翻译自: https://medium.com/python-in-plain-english/getting-started-with-fastapi-in-python-84d7aecc988f