FastAPI 教程:FastAPI+Tortoise-ORM+Celery+Websocket+Redis+PostgreSQL 示例

1. 写在前面

基于 FastAPI 框架,展示 FastAPI + Tortoise-ORM + Celery + Websocket + Redis + PostgreSQL 搭配构建一个简单异步微服务 Demo 示例;

示例地址https://github.com/jianpengzhang/fastapi-common-tmpl

开发文档./docs:

在这里插入图片描述

1. 技术栈

  • Python:3.11.7+;
  • FastAPI: 构建 API Web 框架;
  • Tortoise-ORM:Asyncio ORM (对象关系映射器)库;
  • Celery:分布式任务队列,异步任务/定时任务;
  • Websocket:客户端和 服务器之间的持久性连接,提供双向、 全双工通信;
  • Redis:分布式锁、缓存;
  • PostgreSQL:数据库;

2. 项目结构

$ tree -L 5
.
├── app
│ ├── api                           # Demo:Restful api 接口
│ │ └── v1
│ │     ├── api.py                  # Demo:路由注册
│ │     ├── endpoints
│ │     │ ├── groups.py             # Demo:Group CRUD 接口示例
│ │     │ ├── others.py             # Demo:Redis、Websocket、WS 接口示例
│ │     │ ├── users.py              # Demo:User CRUD 接口示例
│ │     │ └── websockets.py         # Demo:Websocket 接口示例
│ ├── config.py                     # Demo:App Config 配置
│ ├── core
│ │ ├── celery_config.py            # Demo:Celery Config 配置
│ │ ├── celery.py                   # Demo:Celery App 入口
│ │ ├── logger.py                   # Demo:Log 工作库
│ │ ├── redis.py                    # Demo:Redis 工作库
│ │ ├── utils.py                    # Demo:通用工具库
│ │ └── websockets.py               # Demo:基础类及自定义 Websocket
│ ├── main.py                       # Demo:App入口及内置健康检查 API
│ ├── models
│ │ ├── base.py                     # Demo:基础数据模型
│ │ └── examples.py                 # Demo:数据模型(User、Group)
│ ├── schemas
│ │ └── examples.py                 # Demo:定义数据模型 Pydantic 模式(schemas),用于在应用程序中进行数据验证和序列化/反序列化
│ ├── services
│ │ └── examples.py                 # Demo:Services 层示例
│ └── tasks
│     ├── scheduler_tasks.py        # Celery 定时任务
│     └── tasks.py                  # Celery 异步任务
├── docs                            # 开发说明
├── deploy
│ └── docker-compose
│     ├── docker-compose.yml        # docker-compose 部署 yaml 文件 
│     └── env.template              # 环境变量配置
├── Dockerfile                      # 构建容器镜像
├── LICENSE                         # LICENSE 授权
├── migrations                      # 迁移文件
├── pyproject.toml                  # 项目管理
├── README.md                       # 项目说明
├── requirements.txt                # Demo 依赖项
└── tests                           # 单侧用例

3. 项目配置

cp ./deploy/docker-compose/env.template ./deploy/docker-compose/.env

BACKEND_IMAGE=$IMAGE             # 部署镜像
DEBUG=false

# postgres 数据库配置
POSTGRES_HOST=example-postgres   # PostgreSQL 访问地址,默认是容器名称
POSTGRES_PORT=5432               # PostgreSQL 端口,默认 5432
POSTGRES_USER=example             # PostgreSQL 访问用户
POSTGRES_PASSWORD=example123       # PostgreSQL 访问密码
POSTGRES_DB=example              # PostgreSQL 访问数据库
DB_POOL_MAX=100                  # PostgreSQL 最大连接数
DB_POOL_CONN_LIFE=-1

# redis配置
REDIS_HOST=example-redis         # Redis 访问地址,默认是容器名称
REDIS_PORT=6379                  # Redis 端口,默认 6379
REDIS_USER=                      # Redis 访问用户
REDIS_PWD=                       # Redis 访问密码

4. Migrations 数据库迁移

Aerich 是 TortoiseORM 的数据库迁移工具。当前 Demo 示例,会通过 example-migrations 容器完成数据迁移及初始化工作。若有自定义可参考如下命令操作;

(1)初始化:

执行 aerich 初始化:aerich init -t 指定配置,项目初始阶段执行;

aerich init -t config.TORTOISE_ORM

将会在目录下生成空的 migrations 文件夹和 pyproject.toml 文件

(2)初始化数据库

将模型映射到数据库中:

aerich init-db

此时数据库中就会生成对应的表。

(3)【日常命令】更新模型迁移文件

更新数据模型后,重新生成SQL迁移文件。

aerich migrate

(4)【日常命令】升级到最新版本

执行迁移文件更新数据库:

aerich upgrade

或

aerich upgrade xxxxx.py

(5)【日常命令】降级到指定版本

数据库回滚到指定版本:

aerich downgrade

或

aerich downgrade xxxxx.py

(6)【日常命令】查看历史迁移记录

aerich history

(7)【日常命令】显示迁移的 heads

aerich heads

5. Docker 部署

下载代码,例:git clone xxxx.xxx.xxx

(1)构建镜像

# 进入 Demo 根目录
cd ./fastapi-common-tmpl

# 构建镜像 1.0
docker build -t fastapi-common-tmpl:1.0 .

# 检查镜像
docker images | grep fastapi-common-tmpl

(2)env 环境变量配置

修改环境变量: mv ./deploy/docker-compose/env.template ./deploy/docker-compose/.env

# 指定 Demo 部署版本
BACKEND_IMAGE=fastapi-common-tmpl:1.0

# 数据库配置
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_USER=example
POSTGRES_PASSWORD=example123
POSTGRES_DB=example
DB_POOL_MAX=100
DB_POOL_CONN_LIFE=-1

# Redis 配置
REDIS_HOST=redis
REDIS_PORT=6379

(3)docker-compose 部署

根据需要修改:volumes 挂载点


vi ./deploy/docker-compose/docker-compose.yml

...
volumes:
  example-data-postgres:
    name: example-data-postgres
    driver: local
    driver_opts:
      o: bind
      type: none
      # 自定义 Host 挂载点
      device: /data/example/postgres
  example-data-redis:
    name: example-data-redis
    driver: local
    driver_opts:
      o: bind
      type: none
      # 自定义 Host 挂载点
      device: /data/example/redis

例如:

sudo mkdir /data/example/postgres
sudo mkdir /data/example/redis

启动:

docker-compose -f ./deploy/docker-compose/docker-compose.yml up -d

关闭:

docker-compose -f ./deploy/docker-compose/docker-compose.yml down

检查服务状态:

linux@jpzhang-dev:~/workspace/fastapi-common-tmpl$ docker ps -a

CONTAINER ID   IMAGE                   COMMAND                   CREATED         STATUS                            PORTS                                       NAMES
e0472333beb8   fastapi-common-tmpl:1.5   "celery -A app.core.…"   5 seconds ago   Up 3 seconds                                                                  example-celery
e5e97d5cb8c9   fastapi-common-tmpl:1.5   "celery -A app.core.…"   5 seconds ago   Up 3 seconds                                                                  example-scheduler
f978ad857466   fastapi-common-tmpl:1.5   "uvicorn app.main:ap…"   5 seconds ago   Up 3 seconds                      0.0.0.0:9000->9000/tcp, :::9000->9000/tcp   example-backend
dc241da98f18   fastapi-common-tmpl:1.5   "python init_data.py"     5 seconds ago   Exited (0) 2 seconds ago                                                      example-migrations
a72f7811771b   postgres:14.13          "docker-entrypoint.s…"   5 seconds ago   Up 4 seconds (health: starting)   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   example-postgres
430276b3216c   redis:7.0.15            "docker-entrypoint.s…"   5 seconds ago   Up 4 seconds (healthy)            0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   example-redis

服务介绍:

  • example-celery: Celery 异步任务服务;
  • example-scheduler: Celery 定时任务服务;
  • example-backend: 示例 Demo API 服务;
  • example-migrations: 数据库迁移及数据初始化服务,仅运行一次;
  • example-postgres: PostgreSQL 服务;
  • example-redis: Redis 服务;

(4)Demo Swagger UI

访问地址:http://<HOST IP>:9000/docs/

感谢您花时间阅读文章!
关注公众号不迷路!
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 FastAPITortoise-ORM、SQLAlchemy 和 peewee 进行 ORM 查询的示例。 ## Tortoise-ORM ```python from fastapi import FastAPI from tortoise import fields from tortoise.contrib.fastapi import register_tortoise, HTTPNotFoundError from tortoise.models import Model from tortoise import Tortoise class User(Model): id = fields.IntField(pk=True) name = fields.CharField(50) email = fields.CharField(50) class Meta: table = "users" app = FastAPI() @app.on_event("startup") async def startup(): await Tortoise.init( db_url="sqlite://db.sqlite3", modules={"models": ["main"]} ) await Tortoise.generate_schemas() @app.on_event("shutdown") async def shutdown(): await Tortoise.close_connections() @app.get("/users") async def get_users(): users = await User.all() return users @app.get("/users/{user_id}") async def get_user(user_id: int): user = await User.get_or_none(id=user_id) if user is None: raise HTTPNotFoundError return user register_tortoise( app, db_url="sqlite://db.sqlite3", modules={"models": ["main"]}, generate_schemas=True, add_exception_handlers=True ) ``` ## SQLAlchemy ```python from fastapi import FastAPI from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) name = Column(String(50)) email = Column(String(50)) engine = create_engine("sqlite:///db.sqlite3") SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) app = FastAPI() @app.get("/users") async def get_users(): db = SessionLocal() users = db.query(User).all() db.close() return users @app.get("/users/{user_id}") async def get_user(user_id: int): db = SessionLocal() user = db.query(User).filter(User.id == user_id).first() db.close() if user is None: raise HTTPNotFoundError return user ``` ## peewee ```python from fastapi import FastAPI from peewee import SqliteDatabase, Model, CharField, IntegerField from playhouse.shortcuts import model_to_dict db = SqliteDatabase("db.sqlite3") class User(Model): id = IntegerField(primary_key=True) name = CharField() email = CharField() class Meta: database = db table_name = "users" app = FastAPI() @app.on_event("startup") def startup(): db.connect() db.create_tables([User]) @app.on_event("shutdown") def shutdown(): db.close() @app.get("/users") async def get_users(): users = [model_to_dict(user) for user in User.select()] return users @app.get("/users/{user_id}") async def get_user(user_id: int): user = User.get_or_none(User.id == user_id) if user is None: raise HTTPNotFoundError return model_to_dict(user) ``` 注意:以上示例中的代码仅用于演示 ORM 查询的基本用法,并且没有进行错误处理。在实际应用中,你应该根据需要添加适当的错误处理和安全性检查。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值