FastAPI 是一个用于构建API(网络数据接口)的现代、高性能的Web框架,基于Python 3.6+,使用了Python中的类型提示进行类型检查,非常符合工程化开发的需求,在业界有非常好的口碑。下面,先用代码告诉大家FastAPI到底能做什么,然后再来讲解它的方方面面。

FastAPI五分钟上手

FastAPI 的核心目标是提供一个简单、快速、易用的现代Web框架。它强调了开发效率和代码的可读性,可以帮助开发者更加快速地开发出高性能的API。

在五分钟内,我们可以通过以下几个步骤快速上手FastAPI:

  1. 安装依赖库和ASGI服务器(支持异步I/O的Python服务器)。

    pip install fastapi
    pip install uvicorn
    
  2. 编写代码main.py

    from fastapi import FastAPI
    
    app = FastAPI()
    
    @app.get('/')
    def say_hello():
        return {'code': 200, 'message': 'hello, world!'}
    
  3. 运行服务。

    uvicorn main:app --reload
    
    说明:上面运行uvicorn时使用的--reload参数会在代码发生变更时自动重新加载新的内容,这个参数在开发阶段非常的有用。
  4. 访问服务。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NKR8CbM0-1681296439192)(res/run-first-demo.png)]

    我们可以看到,通过以上四个简单的步骤,我们就可以在浏览器中访问到一个FastAPI应用程序。如果我们想要查看API的文档,只需要在浏览器中访问http://localhost:8000/docs即可。

请求和响应

在FastAPI中,我们可以使用GETPOSTPUTDELETE等RESTful API方式来实现服务的请求和响应。我们通过定义视图函数,将其装饰为对应的请求方法,然后在函数中实现对应的业务逻辑就好了。FastAPI会自动根据参数注解、返回类型注解等信息,为我们生成对应的文档和类型检查。

例如,我们可以定义一个POST请求,用来接收一个JSON格式的请求体,然后返回一个JSON格式的响应。代码如下:

from fastapi import FastAPI

app = FastAPI()

@app.post('/test')
def test(payload: dict):
    return {'status': 'OK', 'payload': payload}

在上面的代码中,我们定义了一个/test的POST请求,该请求接收一个名为payload的JSON请求体,然后返回一个名为status的字符串和一个名为payload的JSON响应体。如果我们访问http://localhost:8000/docs,就可以看到如下的API文档:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K08beY4x-1681296439193)(res/request-response-example.png)]

我们可以看到,FastAPI根据我们的代码自动生成了API文档,包括了请求和响应的格式、参数的类型、参数的描述等信息。

接入关系型数据库

我们可以使用SQLAlchemy三方库来实现对关系型数据库的接入。SQLAlchemy是一个ORM(对象关系映射)框架,ORM框架可以解决Python程序的面向对象模型和关系型数据库的关系模型并不匹配的问题,使得我们可以用面向对象的方式实现数据的CRUD操作。

使用SQLAlchemy连接数据库的步骤如下:

  1. 安装依赖库。

    pip install sqlalchemy
    
  2. 编写代码。

    from sqlalchemy import create_engine, Column, Integer, String
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy.ext.declarative import declarative_base
    
    engine = create_engine('postgresql://user:password@localhost:5432/dbname')
    
    Base = declarative_base()
    
    class User(Base):
        __tablename__ = 'users'
    
        id = Column(Integer, primary_key=True, index=True)
        name = Column(String)
        email = Column(String, unique=True)
        password = Column(String)
    
    Base.metadata.create_all(bind=engine)
    
    SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    
  3. 使用Session进行数据库操作。

    from fastapi import FastAPI, Depends
    from sqlalchemy.orm import Session
    
    app = FastAPI()
    
    def get_db():
        db = SessionLocal()
        try:
            yield db
        finally:
            db.close()
    
    @app.get('/users/{user_id}')
    def get_user(user_id: int, db: Session = Depends(get_db)):
        return db.query(User).filter(User.id == user_id).first()
    

在上面的代码中,我们使用了SQLAlchemy来连接一个名为dbname的PostgreSQL数据库,并定义了一个users表。然后,我们定义了一个get_db函数来获取数据库的Session对象,并使用Depends装饰器将其注入到FastAPI的视图函数中。

依赖注入

FastAPI支持依赖注入,我们可以使用Depends装饰器来声明一个依赖,它可以是一个函数、一个类、一个参数,甚至是一个异步函数。在请求到达视图函数之前,FastAPI会先解析依赖关系,将依赖的对象传递给视图函数,使得我们可以在函数中使用这些对象。

例如,我们可以定义一个依赖,用来获取当前用户的信息:

from fastapi import FastAPI, Depends

app = FastAPI()

def get_current_user(token: str = Depends(get_token)):
    return User(token)

@app.get('/users/me')
def read_current_user(current_user: User = Depends(get_current_user)):
    return current_user

在上面的代码中,我们定义了一个get_current_user函数作为依赖,用来获取当前用户的信息。然后,我们定义了一个read_current_user函数,它的参数中包含了一个current_user参数,该参数的类型为User,表示当前用户的信息。在执行read_current_user函数之前,FastAPI会先执行get_current_user函数,并将其返回的User对象注入到read_current_user函数中。

中间件

FastAPI支持中间件,中间件是一种在请求到达视图函数之前或之后,对请求进行处理的机制。我们可以使用中间件来进行请求响应日志的记录、权限校验、异常处理等。

例如,我们可以定义一个中间件,用来记录请求的响应时间:

from fastapi import FastAPI, Request

app = FastAPI()

@app.middleware('http')
async def log_request(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    end_time = time.time()
    duration = end_time - start_time
    logger.info(f'{request.method} {request.url.path} {response.status_code} {duration}s')
    return response

在上面的代码中,我们定义了一个名为log_request的中间件,它接收一个Request对象和一个call_next函数作为参数。在函数体内,我们记录了请求的开始时间,然后调用call_next函数继续处理请求,并记录了请求的结束时间。最后,我们在日志中输出了请求的方法、路径、响应状态码和响应时间。

异步化

FastAPI天生支持异步I/O,使用异步I/O可以使得我们的Web服务更加高效、高并发。我们可以使用Python的异步框架asyncio、异步HTTP客户端httpx等,来实现异步I/O的功能。

例如,我们可以使用httpx库来实现异步的HTTP请求:

import httpx

async def async_request(url: str):
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        return response.text

在上面的代码中,我们使用了httpx库来发送一个异步的HTTP请求,然后返回响应的文本内容。

虚拟化部署(Docker)

Docker是一个开源的应用容器引擎,可以让开发者打包应用程序以及其依赖项到一个可移植的容器中,然后发布到任何流行的Linux或Windows机器上,也可以实现云端部署。我们可以使用Docker将FastAPI应用程序打包成一个镜像,然后在任何支持Docker的环境中进行部署。

例如,我们可以使用以下Dockerfile来构建一个FastAPI应用程序的Docker镜像:

FROM python:3.8-slim-buster

WORKDIR /app

COPY requirements.txt .

RUN pip install -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

在上面的Dockerfile中,我们首先基于一个Python 3.8的slim镜像构建一个Docker镜像,然后将代码和依赖项复制到镜像中,并安装依赖项。最后,我们使用uvicorn命令启动FastAPI应用程序,并将其绑定到0.0.0.0:8000地址上。

项目实战:车辆违章查询

我们可以使用FastAPI来实现一个车辆违章查询的API。首先,我们需要准备好违章查询的数据源,可以使用第三方的数据源,也可以自己爬取数据。然后,我们需要设计好API的接口,定义好请求和响应的数据格式。最后,我们通过FastAPI框架实现对应的业务逻辑,并将应用部署到云端。

例如,我们可以定义以下API接口:

from fastapi import FastAPI

app = FastAPI()

@app.get('/car-records/{car_number}')
def get_car_records(car_number: str):
    records = query_car_records(car_number)
    return {'records': records}

@app.post('/car-record')
def add_car_record(record: CarRecord):
    add_car_record_to_database(record)
    return {'status': 'OK', 'message': 'Car record added successfully.'}

在上面的代码中,我们定义了两个API接口:一个用于查询车辆的违章记录,一个用于添加车辆的违章记录到数据库中。在查询车辆的违章记录时,我们首先查询数据库中是否存在该车辆的记录,如果存在就返回记录,否则就返回空数组。在添加车辆的违章记录时,我们首先将记录添加到数据库中,然后返回添加成功的消息。

总结:

FastAPI是一个非常优秀的Python Web框架,它具有快速、易用、高性能等特点。通过本文的介绍,我们可以看到FastAPI的灵活性和强大的功能,可以帮助我们更加快速地开发出高性能的API。