赞
踩
该数据模型参照Django的数据模型,因此使用上与Django的数据模型高度相似。
!!! 注意,tortoise-orm是异步框架。
官方文档:
https://tortoise-orm.readthedocs.io/en/latest/index.html
pip install tortoise
pip install aerich==0.6.3
我用的mysql,因此还需要安装aiomysql包:
pip install aiomysql
aerich的功能类似于django的migrate。
TORTOISE_ORM = { "connections": { "default": { 'engine': 'tortoise.backends.mysql', # MySQL or Mariadb 'credentials': { 'host': '127.0.0.1', 'port': '3306', 'user': 'root', 'password': '*****', 'database': 'test', 'minsize': 1, 'maxsize': 5, 'charset': 'utf8mb4', 'echo': True } } }, "apps": { "models": { "models": ["your_models_path", "aerich.models"], # your_models_path: 例如my_api.models; # aerich.models必须要有,但不用创建对应的models文件 "default_connection": "default", } }, "use_tz": False, # 建议不要开启,不然存储日期时会有很多坑,时区转换在项目中手动处理更稳妥。 "timezone": "Asia/Shanghai" }
from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise
api_app = FastAPI()
api_app.include_router(routers.meta_router, prefix="/v1/meta")
register_tortoise(
app=api_app,
config=TORTOISE_ORM,
# generate_schemas=True, # 如果数据库为空,则自动生成对应表单,生产环境不要开
# add_exception_handlers=True, # 生产环境不要开,会泄露调试信息
)
# 创建models.py文件,即TORTOISE_ORM中models参数中指定的models文件。 from tortoise import fields from tortoise.models import Model class DateTimeModel(Model): created_at = fields.DatetimeField(auto_now_add=True, description="创建时间") updated_at = fields.DatetimeField(auto_now=True, description="更新时间") class Meta: abstract = True # 抽象模型,将不会在数据库中创建表 class CoreUser(DateTimeModel): id = fields.IntField(pk=True, index=True) username = fields.CharField(max_length=255, description="用户姓名") # 与django不同的是,这里的description可以直接在数据库表中看到哦。 password = fields.CharField(max_length=255, description="用户密码") # 密码不要存明文,存hash值。 is_delete = fields.BooleanField(default=False, description="是否删除") class Meta: table = "core_user" # 数据库中的表名称
1. 打开命令行,切换到项目根目录 2. 初始化配置项 aerich init -t db.config.TORTOISE_ORM 初始化完成后会在当前目录生成一个文件pyproject.toml和一个文件夹migrations · pyproject.toml: 保存配置文件路径 . migrations:存放.sql迁移文件 3. 初始化数据库,一般情况下只用一次 aerich init-db · 如果TORTOISE_ORM配置文件中的models改了名,执行这条命令时需要增加--app参数,来指定你修改的名字。 · 在migrations的指定app目录下生成sql文件(如果model不为空时),并在数据库中生成表。 4. 更新模型并进行迁移 aerich migrate --name any_name · 每次修改model后执行此命令,将在migrations文件夹下生成.sql迁移文件; · --name参数为你的迁移文件添加备注,默认为update; · 迁移文件名的格式为{version_num}{datetime}{any_name|update}.sql; · 如果aerich识别到您正在重命名列,它会要求重命名{old_column}为{new_column} [True],您可以选择True 重命名列而不删除列,或者选择False删除列然后创建,如果使用Mysql,只有8.0+支持重命名。 5. 更新最新修改到数据库 aerich upgrade [xxx.sql] 6. 后续每次修改models文件内容(新增、删除或修改数据模型, 非models文件重命名),只需执行步骤4、5即可。 7. 其它操作 a. 降级到指定版本 aerich downgrade -v 指定版本 -d 降级的同时删除迁移文件 --yes 确认删除,不再交互式输入 b. 显示当前可以迁移的版本 aerich heads c. 显示迁移历史 aerich history 8. 查看数据库,验证迁移操作。
from fastapi import APIRouter meta_router = APIRouter() # 需要在app中进行注册 # api_app = FastAPI() # api_app.include_router(routers.meta_router, prefix="/v1/meta") @meta_router.post("/user/createUser") async def create_user(user: CreateUser): core_suer = await CoreUser.create(**user.dict()) # 操作也与django保持高度一致,返回创建成功的CoreUser对象 return core_suer.id @meta_router.put("/user/updateUser") async def create_user(user: UpdateUser): num = await CoreUser.filter(id=user.user_id).update( username=user.username, password=user.password ) return num # 受影响的笔数,如果数据没有任何变化,则返回0条。注意这里返回值与django有差异,更实用。 @meta_router.get("/user/list") async def get_user_list(): query_set = await CoreUser.all() # 注意这里返回的query_set实际是个列表。List[CoreUser] records = [] count = len(query_set) for obj in query_set: records.append(dict( username=obj.username, password=obj.password, )) return dict(count=count, records=records) @meta_router.get("/user/info") async def get_user(user_id): obj = await CoreUser.filter(id=user_id).first() return dict(username=obj.username, password=obj.password)
使用下面两种方式,都可以保证所属的数据库操作都在同一个事务中执行,如果中间有代码执行失败,已经执行的数据库操作会被回滚。
# 装饰器针对整个被修饰的方法
from tortoise import transactions
@transactions.atomic()
async def create_user():
pass
# in_transaction针对with语句下的所有操作
from tortoise import transactions
async def create_user():
async with transactions.in_transaction():
pass
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。