FastAPI 学习 - 环境配置和运行服务
最近FastApi非常火, 而且据说性能也非常不错, 于是打算学习一下. 写个博客项目顺便练习一下异步请求等的使用.
这是我的公开学习仓库
1. 首先是配置环境.
这里我都选择的是官方文档推荐的组件
组件 | python包 | 版本 |
---|---|---|
后台框架 | FastApi | 0.100.1 |
ORM | Tortoise-ORM | 0.19.3 |
序列化器 | Pydantic | 1.10.12 |
ASGI | Uvicorn | 0.23.2 |
缓存 | Redis | 4.6.0 |
数据库驱动 | asyncpg | 0.27.0 |
数据库迁移工具 | aerich | 0.7.1 |
数据库: PostgreSQL 15
**记录一个使用中遇到的小坑
在所有包使用最新版的情况下总是会遇到pydantic 在使用pydantic_model_creator的时候总是会遇到一个keyerror报错(甚至是直接拷贝使用官方文档给出的demo代码), 本人能力有限, 除了直接改包里的源代码外无法解决这个问题, 各种创建方法和参数都尝试过了, 于是尝试降级了部分包版本, 目前以我上面表格列出的包版本来讲是没有问题的(如果有问题也不要找我)
确定项目运行正常之后又手动升级了部分包的版本, 这里给出我requirements:
aerich==0.7.1
aiosqlite==0.17.0
anyio==3.7.1
async-timeout==4.0.2
asyncpg==0.27.0
bcrypt==4.0.1
cffi==1.15.1
click==8.1.6
dictdiffer==0.9.0
ecdsa==0.18.0
fastapi==0.100.1
h11==0.14.0
idna==3.4
iso8601==1.1.0
passlib==1.7.4
pyasn1==0.5.0
pycparser==2.21
pydantic==1.10.12
pypika-tortoise==0.1.6
python-dotenv==1.0.0
python-jose==3.3.0
pytz==2023.3
redis==4.6.0
rsa==4.9
six==1.16.0
sniffio==1.3.0
starlette==0.27.0
tomlkit==0.12.1
tortoise-orm==0.19.3
typing_extensions==4.7.1
uvicorn==0.23.2
2. 初始化APP
结束环境配置之后需要初始化app
这一步主要是完成了注册和初始化数据库
注册redis
然后把自定义的一些模块和路由注册到app中
def register_redis(app: FastAPI):
"""
register redis to app
"""
@app.on_event("startup")
async def startup_event():
app.redis = await redis.from_url(REDIS_URL, decode_responses=True, encoding="utf8", )
# @app.on_event("shutdown")
# async def shutdown_event():
# app.redis.close()
def init_db(app):
"""
initialise database
"""
register_tortoise(
app,
config=TORTOISE_ORM,
add_exception_handlers=True,
)
def register_router(app):
"""
register router to app
"""
Tortoise.init_models(['common.models', 'user.models', 'article.models'], 'models')
app.include_router(
article_router,
tags=['article'],
responses={404: {'description': 'Not Found'}},
prefix='/api/article',
)
app.include_router(
user_router,
tags=['user'],
responses={404: {'description': 'Not Found'}},
prefix='/api/user',
)
app.include_router(
test_router,
tags=['test'],
responses={404: {'description': 'Not Found'}},
prefix="/api/test",
)
def create_app():
app = FastAPI()
app.mount(
"/static",
StaticFiles(directory=os.path.join(BASE_DIR, "statics")),
name="static",
)
origins = [
"http://localhost",
"http://localhost:19988",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["*"],
)
init_db(app)
register_router(app)
register_redis(app)
return app
3.创建模型及关系
这是部分models 文件
common.models.py
from tortoise import fields, models
class BaseModel(models.Model):
"""
The Base model
"""
id = fields.UUIDField(pk=True)
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
class Meta:
abstract = True
class Tag(BaseModel):
"""
The Tag model
"""
name = fields.CharField(max_length=128, null=False, unique=True, index=True)
class Meta:
table = "tb_tag"
# @property
def key(self) -> str:
return self.name
user.models.py
from tortoise import fields
from common.models import BaseModel
class User(BaseModel):
"""
The User model
"""
username = fields.CharField(max_length=32, null=True, index=True, unique=True)
phone = fields.CharField(max_length=13, null=True, unique=False, index=True)
password = fields.CharField(max_length=256, null=False)
introduction = fields.CharField(max_length=512, null=True)
avatar = fields.CharField(max_length=50, null=True)
email = fields.CharField(max_length=128, null=True, unique=True, index=True)
last_login = fields.DatetimeField(null=True, auto_now=True)
disabled = fields.BooleanField(default=False, index=True)
tags = fields.ManyToManyField(
'models.Tag',
related_name='users',
through='rs_user_tag',
null=True,
on_delete=fields.SET_NULL,
)
class Meta:
table = "tb_user"
4. 创建Pydantic
这里使用pydantic主要用作序列化器
common.pydantics.py
from tortoise.contrib.pydantic import pydantic_model_creator
from common.models import Tag
Tag_Pydantic = pydantic_model_creator(
Tag,
name="TagPydantic",
computed=('key',)
)
TagIn_Pydantic = pydantic_model_creator(Tag, name="TagIn", exclude_readonly=True)
user.pydantics.py
from tortoise.contrib.pydantic import pydantic_model_creator
from pydantic import BaseModel
from user.models import User
class UserLoginPydantic(BaseModel):
username: str
password: str
UserPydantic = pydantic_model_creator(User, name="UserPydantic")
UserInfoPydantic = pydantic_model_creator(
User,
name="UserInfo",
exclude=('password', 'last_login', 'created_at', 'updated_at', 'disabled'),
)
5. 使用aerich迁移数据库
首先初始化数据库配置文件
aerich init -t config.settings.TORTOISE_ORM
初始化数据库
aerich init-db
这一步会默认生产一个init的migration py文件并自动执行用来初始化数据表
后续如果模型有改动的话先执行aerich migrate
生成迁移py文件 然后执行 aerich upgrade
进行升级迁移就好
6. 添加一个test api
common.apis.py
from fastapi import APIRouter, status
router = APIRouter()
@router.get('/get/')
def test_get_method():
return {'code': status.HTTP_200_OK, 'data': {'message': 'test get method OK.'}}
7. 运行服务
uvicorn main:app --host 0.0.0.0 ---port 9988 --reload
使用这个命令运行一个开发服务接受局域网任意ip访问本机端口9988, 当文件改动保存时会自动重启服务
app 是你的app名 如果你是 test=FastAPI() 那么你就使用uvicorn main:test --host 0.0.0.0 ---port 9988 --reload
这时候可以打开http://127.0.0.1:9988/docs/查看你的服务
后续如果有遇到其他问题 我会继续更新
仓库中的web是fork别人的blog前端vue模板, 并没有进行接口调通, 后面有时间的话会弄
欢迎关注此代码仓库, 如果觉得有用请给我一个🌟