FastAPI + PostgreSQL 实战:从入门到不踩坑,一次讲透

🧐 第一部分:为什么是PostgreSQL?

你可以把PostgreSQL想象成一个**"极度守规矩的档案管理员"**------数据完整性、ACID、复杂查询支持得滴水不漏。

相比MySQL,它对JSON、全文检索、地理空间数据的支持更原生,而且这几年性能优化得特别猛。

最关键的是,它和FastAPI的异步生态配合得非常好,后面你会体会到。

⚙️ 第二部分:安装PostgreSQL(Docker一键搞定)

最怕那种"双击安装包一路下一步"然后环境变量配半小时的教程。咱们用Docker,干净利落。

复制代码
docker run -d \
  --name postgres-demo \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -e POSTGRES_USER=myuser \
  -e POSTGRES_DB=mydb \
  -p 5432:5432 \
  postgres:15

然后你就可以用任何客户端(比如TablePlusDBeaver )连上localhost:5432验证一下。记得密码别写死在代码里,后面咱们用环境变量。

敲黑板: 本地开发千万别用root用户,上面我特意建了普通用户myuser,权限最小化原则。

📦 第三部分:FastAPI项目初始化

创建一个新目录,弄个虚拟环境,然后装依赖。这里我推荐两个库

asyncpg ------ PostgreSQL的异步驱动,性能爆表。

databases ------ 封装了连接池和查询,让你能用async/await执行SQL,还支持SQLAlchemy Core(可选)。

当初我图省事直接用了同步的psycopg2,结果FastAPI异步线程被阻塞,性能直接打骨折。所以,一定一定要用异步驱动!

安装命令:

复制代码
pip install fastapi uvicorn databases[asyncpg] python-dotenv

💻 第四部分:写代码,让FastAPI和PG连上线

先建一个.env文件存放敏感信息:

复制代码
DATABASE_URL=postgresql://myuser:mysecretpassword@localhost/mydb

然后写主程序main.py

复制代码
import os
from fastapi import FastAPI
from contextlib import asynccontextmanager
from databases import Database
from dotenv import load_dotenv

load_dotenv()

DATABASE_URL = os.getenv("DATABASE_URL")
database = Database(DATABASE_URL)

@asynccontextmanager
async def lifespan(app: FastAPI):
    await database.connect()
    # 创建表(实际项目用Alembic,这里演示直接执行SQL)
    query = """CREATE TABLE IF NOT EXISTS users (
        id SERIAL PRIMARY KEY,
        username VARCHAR(50) UNIQUE NOT NULL,
        email VARCHAR(100) UNIQUE NOT NULL
    );"""
    await database.execute(query=query)
    print('数据表创建完成!')
    yield
    await database.disconnect()

app = FastAPI(lifespan=lifespan)

@app.get("/users")
async def get_users():
    query = "SELECT id, username, email FROM users"
    results = await database.fetch_all(query=query)
    return [dict(r) for r in results]

@app.post("/users")
async def create_user(username: str, email: str):
    # 简单的插入,实际要加异常处理
    query = "INSERT INTO users(username, email) VALUES (:username, :email) RETURNING id"
    values = {"username": username, "email": email}
    user_id = await database.execute(query=query, values=values)
    return {"id": user_id, "username": username, "email": email}

启动服务:uvicorn main:app --reload。打开http://localhost:8000/docs,你就能看到自动生成的API文档,试一下POST和GET,是不是很爽?

⚠️ 第五部分:那些年我踩过的坑(精华)

🚨 坑1:连接被拒绝

现象:ConnectionRefusedError。大概率是Docker容器端口没映射出来,或者PostgreSQL配置只绑定了127.0.0.1。用Docker一定要加-p 5432:5432。另外检查防火墙。

🚨 坑2:asyncpg.exceptions.InvalidPasswordError

密码错误?其实很多时候是因为URL格式不对。注意postgresql://user:pass@host/db,特殊字符要URL编码。

🚨 坑3:在异步函数里用了同步的psycopg2连接

这会导致事件循环阻塞,性能急剧下降。解决方案就是全程用asyncpgdatabases

🚨 坑4:事务忘记commit?

database.transaction()上下文管理器最安全:

复制代码
async with database.transaction():
    await database.execute(query1)
    await database.execute(query2)  # 如果出错,自动回滚

🚨 坑5:连接池耗尽

默认连接池大小可能不够,高并发时需调整:

复制代码
database = Database(DATABASE_URL, min_size=5, max_size=20)
相关推荐
不会就选b6 小时前
MySQL之视图
数据库·mysql
>no problem<6 小时前
基于cola5.0的基础设施层的多数据库切换方案思路
数据库·spring boot·mybatisplus·cola5.0·数据库迁移适配
OceanBase数据库官方博客6 小时前
OceanBase 赋能央国企:从发电到用电的全链路业务承载
数据库·oceanbase
瀚高PG实验室7 小时前
pgsql-ogr-fdw
数据库·postgresql·瀚高数据库·highgo
IvorySQL7 小时前
PostgreSQL 技术日报 (6月5日)|PG19 Beta1 上线,PGConf.PL 2026开启征稿
数据库·postgresql·区块链
abcy0712138 小时前
pycharm python sqlalchemy mysql增删改查实例csdn
数据库·oracle
无风听海8 小时前
IndexedDB 深度指南 浏览器中的事务型对象数据库
前端·数据库
咋吃都不胖lyh8 小时前
langgraph基础示例
数据库
网管NO.19 小时前
子查询进阶|EXISTS/IN/ANY/ALL,优化查询效率
数据库·sql
云服务器租用费用9 小时前
2026年腾讯云OpenClaw(Clawdbot)+Skills云上部署及Windows本地集成轻松入门
运维·服务器·数据库·windows·云计算·腾讯云