真正可落地、工程级的 FastAPI + PostgreSQL + Vue 数据展示平台方案,包括:
- 项目架构
- 技术选型
- 后端 / 前端目录结构
- 数据库设计
- API 示例
- 前端展示示例
- 实际部署方式(Docker)
🚀 目标
构建一个 数据展示平台:
- 后端:FastAPI
- 数据库:PostgreSQL
- 前端:Vue 3 + Element Plus
- 支持数据表格展示、搜索、图表展示(ECharts)
- REST API
- 跨域
- Token 登录(可选)
🧱 一、整体架构(推荐使用)
┌──────────────────────────┐
│ Vue (前端) │
│ Vite + Vue3 + ElementUI │
└───────────▲──────────────┘
│ axios
(JSON REST API) │
▼
┌──────────────────────────┐
│ FastAPI (后端) │
│ Pydantic / SQLAlchemy │
└───────────▲──────────────┘
│
asyncpg │
▼
┌──────────────────────────┐
│ PostgreSQL (DB) │
└──────────────────────────┘
📁 二、项目目录结构(全栈)
建议使用以下目录结构:
project/
│
├── backend/
│ ├── app/
│ │ ├── main.py
│ │ ├── db.py
│ │ ├── models/
│ │ │ └── user.py
│ │ ├── routers/
│ │ │ ├── user.py
│ │ │ └── data.py
│ │ └── schemas/
│ │ └── user.py
│ │ └── data.py
│ ├── requirements.txt
│
├── frontend/
│ ├── src/
│ ├── vite.config.js
│ └── package.json
│
└── docker-compose.yml
🛢 三、PostgreSQL 配置
安装 PostgreSQL(推荐 Docker)
docker run -d \
--name pg \
-e POSTGRES_USER=admin \
-e POSTGRES_PASSWORD=123456 \
-e POSTGRES_DB=dataplatform \
-p 5432:5432 \
postgres:15
🐍 四、后端 FastAPI 示例(可直接运行)
📌 requirements.txt
fastapi
uvicorn[standard]
sqlalchemy
asyncpg
alembic
pydantic
python-multipart
1️⃣ db.py --- 数据库初始化
python
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker, declarative_base
DATABASE_URL = "postgresql+asyncpg://admin:123456@localhost/dataplatform"
engine = create_async_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
Base = declarative_base()
2️⃣ models/data.py --- 数据模型
python
from sqlalchemy import Column, Integer, String, Float
from ..db import Base
class DataItem(Base):
__tablename__ = "data_items"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
value = Column(Float)
category = Column(String, index=True)
3️⃣ schemas/data.py --- 验证模型
python
from pydantic import BaseModel
class DataItemBase(BaseModel):
name: str
value: float
category: str
class DataItemOut(DataItemBase):
id: int
class Config:
orm_mode = True
4️⃣ routers/data.py --- 数据 API
python
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from ..db import SessionLocal
from ..models.data import DataItem
from ..schemas.data import DataItemOut
router = APIRouter(prefix="/data", tags=["data"])
async def get_db():
async with SessionLocal() as session:
yield session
@router.get("/", response_model=list[DataItemOut])
async def get_all_data(db: AsyncSession = Depends(get_db)):
result = await db.execute(select(DataItem))
return result.scalars().all()
5️⃣ main.py --- 主入口
python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from .routers import data
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Vue 访问
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(data.router)
运行:
uvicorn app.main:app --reload
🎨 五、前端 Vue 项目(Vite + Vue3)
创建项目
npm init vite@latest frontend --template vue
cd frontend
npm install
npm install element-plus echarts axios
1️⃣ src/views/DataTable.vue(展示数据)
vue
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="id" label="ID" width="60" />
<el-table-column prop="name" label="名称" />
<el-table-column prop="value" label="值" />
<el-table-column prop="category" label="分类" />
</el-table>
</template>
<script setup>
import { ref, onMounted } from "vue";
import axios from "axios";
const tableData = ref([]);
onMounted(async () => {
const res = await axios.get("http://localhost:8000/data/");
tableData.value = res.data;
});
</script>
2️⃣ ECharts 图表示例(src/views/DataChart.vue)
vue
<template>
<div ref="chart" style="width: 100%; height: 400px"></div>
</template>
<script setup>
import * as echarts from "echarts";
import { ref, onMounted } from "vue";
import axios from "axios";
const chart = ref(null);
onMounted(async () => {
const res = await axios.get("http://localhost:8000/data/");
const data = res.data;
const option = {
xAxis: { type: "category", data: data.map(d => d.name) },
yAxis: { type: "value" },
series: [{
type: "bar",
data: data.map(d => d.value)
}]
};
echarts.init(chart.value).setOption(option);
});
</script>
🚀 六、最终可部署方案(docker-compose)
docker-compose.yml
yaml
version: "3.9"
services:
postgres:
image: postgres:15
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: 123456
POSTGRES_DB: dataplatform
ports:
- "5432:5432"
backend:
build: ./backend
ports:
- "8000:8000"
depends_on:
- postgres
frontend:
build: ./frontend
ports:
- "80:80"
下面文件结构
前后端分离式的 FastAPI + PostgreSQL + Vue 数据展示平台 ,而且后端 功能模块化 ,不要把所有代码写在一个 main.py 中。
我给你一个 完整的后端 Python 文件架构模板,方便你直接开发。
🏗 后端项目结构(模块化)
backend/
│
├── app/
│ ├── main.py # FastAPI 启动入口
│ ├── core/ # 核心配置和工具
│ │ ├── config.py # 配置文件(数据库、JWT等)
│ │ └── utils.py # 工具函数
│ │
│ ├── db/ # 数据库相关
│ │ ├── base.py # Base ORM 类
│ │ ├── session.py # 数据库连接、Session
│ │ └── init_db.py # 创建表等初始化
│ │
│ ├── models/ # ORM 数据模型
│ │ ├── user.py
│ │ └── data.py
│ │
│ ├── schemas/ # Pydantic 数据验证
│ │ ├── user.py
│ │ └── data.py
│ │
│ ├── routers/ # API 路由
│ │ ├── user.py
│ │ └── data.py
│ │
│ └── dependencies/ # 依赖注入(例如数据库 session)
│ └── db.py
│
├── requirements.txt
└── alembic/ # 数据库迁移(可选)
🔹 各文件功能说明
1. main.py
负责启动 FastAPI 实例,挂载所有路由,添加中间件。
python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.routers import user, data
app = FastAPI(title="Data Platform API")
# 跨域设置(前端 Vue)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 挂载路由
app.include_router(user.router)
app.include_router(data.router)
2. core/config.py
配置数据库连接和其他全局参数。
python
import os
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql+asyncpg://admin:123456@localhost/dataplatform")
SECRET_KEY = os.getenv("SECRET_KEY", "your_secret_key")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60
3. db/session.py
数据库连接池和 Session。
python
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, declarative_base
from app.core.config import DATABASE_URL
engine = create_async_engine(DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
Base = declarative_base()
4. dependencies/db.py
提供数据库 session 依赖注入给路由使用。
python
from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.session import AsyncSessionLocal
async def get_db() -> AsyncSession:
async with AsyncSessionLocal() as session:
yield session
5. models/data.py
示例数据表 ORM 模型。
python
from sqlalchemy import Column, Integer, String, Float
from app.db.session import Base
class DataItem(Base):
__tablename__ = "data_items"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
value = Column(Float)
category = Column(String, index=True)
6. schemas/data.py
Pydantic 验证模型。
python
from pydantic import BaseModel
class DataItemBase(BaseModel):
name: str
value: float
category: str
class DataItemCreate(DataItemBase):
pass
class DataItemOut(DataItemBase):
id: int
class Config:
orm_mode = True
7. routers/data.py
数据 API 路由。
python
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.models.data import DataItem
from app.schemas.data import DataItemOut
from app.dependencies.db import get_db
router = APIRouter(prefix="/data", tags=["data"])
@router.get("/", response_model=list[DataItemOut])
async def get_all_data(db: AsyncSession = Depends(get_db)):
result = await db.execute(select(DataItem))
return result.scalars().all()
8. routers/user.py(示例)
用户登录/注册接口,可按需扩展 JWT。
python
from fastapi import APIRouter
router = APIRouter(prefix="/user", tags=["user"])
@router.get("/ping")
async def ping():
return {"msg": "pong"}
✅ 特点
- 前后端分离:Vue 通过 axios 调用 FastAPI 的 REST API
- 模块化:不同功能(user、data)独立成文件
- 依赖注入 :数据库 session 通过
Depends注入 - 可扩展:后续添加权限、图表、分析模块直接加 routers、schemas、models
- 支持 async:与 PostgreSQL + asyncpg 完美结合
- 方便测试:每个模块都可以独立测试