赞
踩
pip install fastapi
pip install tortoise-orm
pip install aiomysql
pip install aerich
pip install uvicorn
创建文件夹 fastapi-app
,然后创建项目所需文件,创建完成后项目目录格式如下。目前目录创建的都是空白文件,后面再写内容。
.
├── main.py
├── middlewares
│ ├── __init__.py
│ └── auth_middleware.py
├── models
│ ├── __init__.py
│ └── user.py
├── tasks
│ ├── __init__.py
│ └── tasks.py
└── views
├── __init__.py
├── user.py
└── login.py
main.py
文件中创建fastapi
实例。from fastapi import FastAPI
def create_app():
# 创建一个实例
app = FastAPI()
return app
main.py
,添加一个路由。from fastapi import FastAPI
def create_app():
# 创建一个实例
app = FastAPI()
@app.get('/')
def index():
return "Hello World"
return app
app = create_app()
uvicorn main:app --reload
。(venv) ➜ uvicorn main:app --reload
INFO: Will watch for changes in these directories: ['/Users/wxy/fastapi-app']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [1428] using StatReload
INFO: Started server process [1430]
INFO: Waiting for application startup.
INFO: Application startup complete.
http://127.0.0.1:8000
。http://127.0.0.1:8000/docs
查看文档。作为实例项目,下面会完成一个用户的创建、登录,虽然只有两个接口,但是其中包括了MySQL的配置和连接、orm工具和迁移工具的使用、中间件的使用等。后面写一个完整的项目其实也就是按照这两个接口修修改改,就不过多赘述了。
main.py
,配置数据库参数,并且连接数据库。import uvicorn from fastapi import FastAPI from tortoise.contrib.fastapi import register_tortoise TORTOISE_ORM_CONFIG = { 'connections': { 'default': { 'engine': 'tortoise.backends.mysql', 'credentials': { 'host': 'localhost', 'port': '3306', 'user': 'root', 'password': '12345678', 'database': 'fastapp', } }, }, 'apps': { 'models': { # 数据表对应文件, `aerich.models`是迁移工具生成的数据表 'models': ['aerich.models', 'models'], 'default_connection': 'default', } } } def create_app(): # 创建一个实例 app = FastAPI() # 连接数据库 register_tortoise( app, add_exception_handlers=True, config=TORTOISE_ORM_CONFIG, # 生成模式, 自动创建数据表, generate_schemas=False, ) @app.get('/') def index(): return "Hello World" return app app = create_app()
models/user.py
新增User的model数据。from tortoise import fields, Model
class User(Model):
""" 创建user表 """
# pk=True, 设置为主键
id = fields.IntField(pk=True)
name = fields.CharField(max_length=64, description="用户名")
password = fields.CharField(max_length=128, description="登录密码")
create_at = fields.DatetimeField(auto_now_add=True, description="创建时间")
modify_at = fields.DatetimeField(auto_now=True, description="更新时间")
models/__init__.py
中。from models.user import User
viewls/user.py
新增创建用户接口的路由。from fastapi import APIRouter
# 创建一个路由
router = APIRouter(
# 请求路径
prefix="/user",
# 标签, 文档上显示
tags=["登录"],
)
viewls/user.py
文件,添加请求数据的校验和响应数据格式化。from fastapi import Body from pydantic.main import BaseModel from typing import Optional class UserRequest(BaseModel): """ 创建用户接口数据校验 """ # default=..., 是指name字段为必填项, 不写default参数也是默认为必填, 这里加上只是为了更清晰 name: str = Body(default=..., description="用户名") password: str = Body(description="登录密码") # Optional[str]可选项, default=None可以不填或者是填写None email: Optional[str] = Body(default=None, description="邮箱") class UserResponse(BaseModel): """ 创建用户返回数据格式化 """ name: Optional[str] password: Optional[str] email: Optional[str] class Config: # 设置orm_mode=True, 可以在view层直接返回model实例, 并且关联的外键数据也可以直接查出来 orm_mode = True
viewls/user.py
文件,定义创建用户的接口。# response_model=UserResponse, 指定响应数据的格式
# response_model_exclude_none=True, 如果返回的字段=None, 不显示该字段
@router.post('/', response_model=UserResponse, response_model_exclude_none=True)
async def create_user(data: UserRequest):
user = await User.create(
name=data.name,
passsword=data.password,
email=data.email,
)
return user
main.py
文件,把上面定义的创建路由添加到项目中,在create_app
方法最后添加一行app.include_router(user.router)
。import uvicorn from fastapi import FastAPI from tortoise.contrib.fastapi import register_tortoise from views import user TORTOISE_ORM_CONFIG = { 'connections': { 'default': { 'engine': 'tortoise.backends.mysql', 'credentials': { 'host': 'localhost', 'port': '3306', 'user': 'root', 'password': '12345678', 'database': 'fastapp', } }, }, 'apps': { 'models': { # 数据表对应文件, `aerich.models`是迁移工具生成的数据表 'models': ['aerich.models', 'models'], 'default_connection': 'default', } } } def create_app(): # 创建一个实例 app = FastAPI() # 连接数据库 register_tortoise( app, add_exception_handlers=True, config=TORTOISE_ORM_CONFIG, # 生成模式, 自动创建数据表, generate_schemas=False, ) @app.get('/') def index(): return "Hello World" # 添加路由 app.include_router(user.router) return app app = create_app()
到了这里创建用户的接口就算是完成了,但是现在还无法真正的运行起来,如果现在直接运行会提示
tortoise.exceptions.ConfigurationError: default_connection for the model <class 'models.user.User'> cannot be None
这是因为我们创建的User用户表其实还没有在数据库里面创建,需要使用迁移工具更新数据库以后才可以使用。
aerich init -t main.TORTOISE_ORM_CONFIG
main.py
同级目录下会生成一个空的migrations
文件夹,和pyproject.toml
文件, pyproject.toml
内容如下:[tool.aerich]
tortoise_orm = "main.TORTOISE_ORM_CONFIG"
location = "./migrations"
src_folder = "./."
aerich init-db
migrations
文件夹下生成一个models
文件夹, 同时生成一份0_{datetime}_init.sql
数据库迁移文件, 并且在数据库中添加一个名为aerich
的迁移表。-- upgrade --
CREATE TABLE IF NOT EXISTS `aerich` (
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`version` VARCHAR(255) NOT NULL,
`app` VARCHAR(100) NOT NULL,
`content` JSON NOT NULL
) CHARACTER SET utf8mb4;
migrations/models
文件夹中新生成一份1_{datetime}_update.sql
的数据库迁移文件。aerich migrate
aerich upgrade
aerich history
aerich downgrade -v [版本]
aerich heads
启动项目:uvicorn main:app --reload
。
访问文档地址:http://127.0.0.1:8000/docs
。
依次点击
修改请求值(因为email
字段非必填,所以这里没有填写email
参数),然后点击执行按钮。
然后在下面可以看到响应数据,说明用户已经创建完成。
用户创建的接口完成,下面开始写用户的登录接口
views/login.py
,新增一个登录接口。from fastapi import APIRouter, HTTPException, Depends, Body from pydantic import BaseModel from starlette import status from models.user import User router = APIRouter( # 请求路径 prefix="/1/login", # 标签, 文档上显示 tags=["登录"], ) class RequestUserLogin(BaseModel): """ 用户登录请求数据校验 """ phone: str = Body(..., max_length=11, description="登录手机号") password: str = Body(..., description="登录密码") class ResponseUserLogin(BaseModel): """ 用户登录响应数据 """ name: str = None access_token: str = None @router.post("/", response_model=ResponseUserLogin, response_model_exclude_unset=True) async def login(data: RequestUserLogin): """ 登录 :param data: :return: """ user = User.filter(phone=data.phone, password=data.password) if not user: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="用户名或密码错误.") # 生成一个token返回给前端, 做登录校验使用 access_token = "0123456789" return {"access_token": access_token, "name": user.name}
requests
调用一下登录接口,测试接口的可用性(可选)。import requests
url = "http://127.0.0.1:8000/1/login/"
payload = {
"name": "用户名",
"password": "密码123"
}
headers = {
'Authorization': '0123456789',
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, json=payload)
print(response.json())
{
"name": "用户名",
"access_token": "0123456789"
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。