给大家分享一套通用、可迭代、轻量化 Python Web 桌面开发框架 完整落地教程,主打无业务绑定、高复用、可自由拓展 。基于 uv+FastAPI+Jinja2 搭建轻量化Web开发底座,无需前端工程、零复杂配置,支持本地Web服务运行,最终通过 Nuitka 编译为单文件EXE桌面程序,是Python小型Web工具、本地应用开发的通用最优框架方案
本文全程聚焦框架集成、环境配置、工程规范、打包部署,不绑定具体业务功能,搭建完成后可自由拓展各类办公、工具、数据处理业务,新手可直接复刻复用。
一、项目介绍
本项目是一套标准化、模块化、可长期迭代 的 Python 通用Web桌面开发框架,摒弃复杂前后端分离架构,采用 FastAPI 后端服务 +Jinja2 服务端模板渲染 一体化模式,无需Vue/React前端工程,低门槛快速开发本地Web应用。
核心定位:轻量化Python Web桌面开发通用底座
核心优势:零前端工程、结构分层清晰、环境纯净隔离、支持热更新调试、一键打包EXE、可无限拓展业务
适用场景:个人工具开发、小型本地Web应用、私有化轻量服务、小型团队快速迭代项目
二、技术选型
(一)核心技术栈
所有技术组件各司其职,标准化集成,无冗余依赖,适配轻量化桌面Web框架开发:
- 环境管理: **uv,**Rust编写的高速包管理+虚拟环境工具,替代传统pip/venv,实现项目依赖隔离、极速安装、统一环境管理,解决多项目环境冲突问题
- Web 框架: **FastAPI,**高性能异步Web后端框架,作为框架核心服务载体,支撑路由分发、请求处理、业务拓展,性能优异、代码规范简洁
- 模板引擎: **Jinja2,**框架核心渲染组件,实现后端服务端渲染(SSR),支持后端动态变量传参、动态页面渲染,无需独立前端项目
- 文件处理依赖: **python-multipart,**通用文件上传依赖,为框架预留文件上传、批量处理拓展能力
- Web 服务器: **uvicorn,**ASGI异步服务器,FastAPI专属运行载体,负责端口监听、服务启动、请求调度,保障框架稳定运行
- 打包工具: **Nuitka,**Python高级编译打包工具,将完整框架编译为原生单文件EXE,脱离Python环境直接运行,适配桌面分发需求
- 前端 UI 框架 :本地部署 Bootstrap 5.3.8 布局框架 + Bootstrap Icons 1.13.1 图标库,采用Jinja2模板继承架构,实现统一后台布局、主题切换、侧边栏菜单、插槽拓展,全程离线可用,无网络依赖
(二)开发与运行环境
- 开发工具:PyCharm
- 系统环境:Windows 10 / Windows 11
- Python版本:3.10+ 稳定版本
- 环境特性:全自动环境隔离,多项目依赖互不干扰,开箱即用
三、开发规范
框架全程遵循标准化开发规范,统一代码风格、目录结构,方便后期迭代、业务拓展、团队协作:
- 项目文件夹命名:中划线,符合开源项目通用规范
- 代码包命名:下划线,严格遵循Python官方命名规范
- 业务逻辑、路由管理、页面渲染严格分层解耦,结构清晰
- 统一使用 uv 管理虚拟环境与第三方依赖,统一项目构建标准
- 无需手动配置环境变量,全自动初始化开发环境
四、搭建框架
(一)初始化项目
打开 PyCharm → 新建项目,自定义项目名称,使用 PyCharm 默认虚拟环境初始化空白项目。
(二) 环境依赖
在PyCharm终端执行以下命令,完成环境初始化、工具安装、框架依赖批量配置:
bash
# 安装uv环境管理工具
python -m pip install uv -i https://mirrors.aliyun.com/pypi/simple/
# 验证uv安装成功
python -m uv --version
# 初始化空白项目配置文件
python -m uv init --bare
# 安装框架全套核心依赖
python -m uv add fastapi uvicorn jinja2 python-multipart nuitka
(三)目录结构
搭建可复用的分层目录结构,区分服务配置、路由、模板、业务模块,适配所有同类Web项目开发:
bash
project-name/
├── main.py # 项目全局统一启动入口
├── project_name/
│ ├── __init__.py
│ ├── app.py # 项目核心服务入口
│ ├── api/ # api目录
│ ├── service/ # 业务逻辑
│ └── web/
│ ├── static/ # 本地静态资源目录
│ │ ├── lib/
│ │ │ ├── bootstrap/v5.3.8/
│ │ │ └── bootstrap-icons/v1.13.1/
│ │ ├── css/
│ │ │ └── global.css # 全局样式
│ │ └── js/
│ │ ├── main.js
│ │ └── pdf/
│ └── templates/ # Jinja2模板目录
│ ├── layout/
│ │ └── main.html # 全局母版布局
│ ├── pdf/
│ │ └──pdf_merge.html
│ │── error/
│ └── 404.html
│
├── pyproject.toml # uv依赖配置文件
└── README.md
五、核心代码集成
以下为通用无业务框架源码,完成FastAPI、Jinja2、静态资源、UI组件的完整集成,可直接复用至任意项目。
(一)服务配置 app.py
实现FastAPI初始化、Jinja2模板引擎挂载、静态资源配置、基础路由,是整个框架的核心载体:
python
import sys
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.responses import JSONResponse
from pathlib import Path
from wisear_tools.api.v1.pdf_api import router as pdf_router
def create_app():
app = FastAPI(title="通用工具箱")
if getattr(sys, 'frozen', False):
# EXE 运行时:取 exe 所在目录
PROJECT_ROOT = Path(sys.executable).parent
else:
# 开发运行时:保持你原来的路径逻辑
PROJECT_ROOT = Path(__file__).parent.parent
# 静态资源 & 模板目录
web_dir = PROJECT_ROOT / "wisear_tools" / "web"
app.mount("/static", StaticFiles(directory=web_dir / "static"), name="static")
templates = Jinja2Templates(directory=web_dir / "templates")
# 首页&PDF合并页面路由
@app.get("/")
@app.get("/pdf/merge")
async def pdf_merge_page(request: Request):
return templates.TemplateResponse(
name="pdf/merge.html",
request=request,
context={"title": "PDF合并", "active": "pdf_merge"}
)
# 业务接口路由
app.include_router(pdf_router, prefix="/api/v1")
# 自定义404异常处理
@app.exception_handler(404)
async def custom_404(request: Request, exc):
req_path = request.url.path
# API路径返回JSON格式404
if req_path.startswith("/api/"):
return JSONResponse(
status_code=404,
content={"code": 404, "msg": "请求接口不存在", "data": None}
)
# 页面路径返回布局内404视图
return templates.TemplateResponse(
name="error/404.html",
request=request,
context={"title": "页面不存在", "active": ""}
)
return app
app = create_app()
(二)启动入口 main.py
全局统一启动文件,适配开发热更新 与Nuitka打包生产环境,自动区分环境、关闭打包热更新,控制台友好提示:
python
import sys
import uvicorn
HOST = "127.0.0.1"
PORT = 8000
APP_MODULE = "wisear_tools.app:app"
def is_frozen() -> bool:
return getattr(sys, "frozen", False)
if __name__ == "__main__":
print(f"✅ 服务已启动:http://{HOST}:{PORT}")
print(f"👉 请复制上面地址到浏览器打开")
uvicorn.run(
APP_MODULE,
host=HOST,
port=PORT,
reload=not is_frozen(),
workers=1
)
本框架采用Jinja2模板继承架构 ,统一全局布局,所有页面复用侧边栏、顶部导航、主题切换、面包屑等通用结构。前端基于 Bootstrap 5.3.8 + Bootstrap Icons 1.13.1 构建,全部使用**本地静态资源部署**,无CDN依赖,打包后100%离线可用。
核心特性:自适应布局、亮色/暗色主题切换、侧边栏折叠、全屏、刷新、多级菜单、模板插槽拓展。
(三)通用布局页面
本框架采用Jinja2 模板继承架构 ,统一全局布局,所有页面复用侧边栏、顶部导航、主题切换、面包屑等通用结构。前端基于 Bootstrap 5.3.8 + Bootstrap Icons 1.13.1 构建,全部使用**本地静态资源部署**,无CDN依赖,打包后100%离线可用。
核心特性:自适应布局、亮色/暗色主题切换、侧边栏折叠、全屏、刷新、多级菜单、模板插槽拓展。
**1.**核心布局页
html
html
<!DOCTYPE html>
<html lang="zh-CN" data-bs-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}通用工具箱{% endblock %}</title>
<!-- 本地 Bootstrap 5.3.8 -->
<link rel="stylesheet" href="/static/lib/bootstrap/v5.3.8/css/bootstrap.min.css">
<!-- 本地 Bootstrap Icons 1.13.1 -->
<link rel="stylesheet" href="/static/lib/bootstrap-icons/v1.13.1/bootstrap-icons.css">
<!-- 全局自定义样式 -->
<link rel="stylesheet" href="/static/css/global.css">
{% block css %}{% endblock %}
</head>
<body>
<div class="layout-wrapper">
<!-- 侧边栏菜单 -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<div class="sidebar-logo">
<i class="bi bi-box-seam"></i>
<span class="logo-text">ToolBox</span>
</div>
</div>
<div class="sidebar-menu">
<!-- 可无限拓展菜单模块 -->
<div class="menu-item has-child">
<i class="bi bi-file-pdf-fill"></i>
<span class="menu-text">PDF工具</span>
<i class="bi bi-chevron-down menu-arrow"></i>
</div>
<div class="sub-menu">
<a href="/pdf/merge" class="menu-item">
<i class="bi bi-front"></i>
<span class="menu-text">PDF合并</span>
</a>
<a href="/pdf/split" class="menu-item">
<i class="bi bi-scissors"></i>
<span class="menu-text">PDF拆分</span>
</a>
<a href="/pdf/compress" class="menu-item">
<i class="bi bi-file-zip"></i>
<span class="menu-text">PDF压缩</span>
</a>
</div>
<div class="menu-item has-child">
<i class="bi bi-file-text"></i>
<span class="menu-text">文档工具</span>
<i class="bi bi-chevron-down menu-arrow"></i>
</div>
</div>
</aside>
<!-- 主内容区域 -->
<main class="content-container">
<header class="content-header">
<div class="header-left">
<button id="toggleBtn" class="btn btn-sm btn-dark me-3">
<i class="bi bi-list"></i>
</button>
<h6 class="mb-0">通用工具箱</h6>
</div>
<div class="header-right">
<button id="btnRefresh" class="btn btn-sm btn-dark" title="刷新页面">
<i class="bi bi-arrow-clockwise"></i>
</button>
<button id="btnFullscreen" class="btn btn-sm btn-dark" title="全屏切换">
<i class="bi bi-arrows-fullscreen"></i>
</button>
<button id="btnTheme" class="btn btn-sm btn-dark" title="主题切换">
<i class="bi bi-moon-stars"></i>
</button>
</div>
</header>
<div class="content-body">
<div class="container-fluid">
<nav aria-label="breadcrumb" class="mb-4">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="/">首页</a></li>
<li class="breadcrumb-item active" id="pageTitle">功能页面</li>
</ol>
</nav>
<!-- 子页面内容插槽 -->
{% block content %}{% endblock %}
</div>
</div>
</main>
</div>
<script src="/static/js/main.js"></script>
{% block script %}{% endblock %}
</body>
</html>
**2.**功能子页面模板
html
{% extends "layout/main.html" %}
{% block title %}PDF合并 - 文档工具箱{% endblock %}
{% block content %}
<div class="row g-4">
<!-- 左侧配置区:完全适配主题的卡片 -->
<div class="col-lg-4">
<div class="card h-100 shadow-sm">
<!-- 卡片头使用 Bootstrap 主题默认的浅色/深色背景 -->
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-sliders me-2"></i>合并配置</h6>
</div>
<div class="card-body">
<p class="text-muted small mb-4">支持上传多个 PDF 文件,可调整顺序后一键合并导出。</p>
<div class="mb-3">
<label class="form-label fw-medium">选择 PDF 文件</label>
<!-- form-control 会自动适配主题背景/边框 -->
<input class="form-control" type="file" id="fileInput" multiple accept=".pdf">
</div>
<div class="mb-4">
<label class="form-label fw-medium">导出文件名称</label>
<input class="form-control" type="text" id="outputName" value="合并文档">
</div>
<button class="btn btn-primary w-100 py-2 fw-medium" id="mergeBtn">
<i class="bi bi-check-circle-fill me-2"></i>开始合并
</button>
<div id="tips" class="mt-3 text-center small"></div>
</div>
</div>
</div>
<!-- 右侧文件列表:完全适配主题的卡片 -->
<div class="col-lg-8">
<div class="card h-100 shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="mb-0"><i class="bi bi-file-earmark-pdf me-2"></i>已上传文件</h6>
<span class="badge bg-primary" id="fileCount">0 个文件</span>
</div>
<div class="card-body p-0 overflow-auto" style="max-height: calc(100vh - 280px);">
<div id="fileList" class="list-group list-group-flush">
<div class="list-group-item text-center text-muted py-4">
<i class="bi bi-file-earmark-fill d-block mb-2 fs-4"></i>
暂无上传文件
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script src="/static/js/pdf/merge.js"></script>
{% endblock %}
**3++.++**404 通用兜底页面
html
{% extends "layout/main.html" %}
{% block title %}页面不存在{% endblock %}
{% block content %}
<div class="d-flex flex-column align-items-center justify-content-center h-100">
<h1 class="display-1 text-primary">404</h1>
<h4 class="my-3">访问的页面不存在</h4>
<a href="/" class="btn btn-primary px-4 py-2">返回首页</a>
</div>
{% endblock %}
六、启动测试
(一)开发环境启动命令
终端执行标准化启动命令,开启热更新,支持开发过程实时调试:
bash
python -m uv run uvicorn project_name.app:app --host 127.0.0.1 --port 8000 --reload
(二)框架访问验证
启动成功后,浏览器访问:http://127.0.0.1:8000
页面正常渲染、后端动态变量展示正常、UI样式适配完成,代表整套框架集成成功,可自由拓展业务功能。
**七、**Nuitka 框架一键打包配置
框架开发完成后,可通过Nuitka一键打包为独立EXE程序,脱离Python环境运行,适配桌面分发场景,打包脚本通用可复用:
(一)一键打包脚本 build.bat
bash
@echo off
python -m uv run nuitka ^
--onefile ^
--windows-console-mode=force ^
--include-package=project_name ^
--include-data-dir=project_name/web/static=project_name/web/static ^
--include-data-dir=project_name/web/templates=project_name/web/templates ^
--output-dir=dist ^
--output-filename=web-framework.exe ^
main.py
pause
**(二)**打包核心参数说明
- --onefile:打包为单文件EXE,简洁易分发
- --windows-console-mode=force:保留控制台日志,便于排查运行异常
- --include-data-dir:强制打包模板与静态资源,解决打包后页面空白、资源丢失问题
八、框架优势
- 技术栈轻量化:无需前端工程、无需复杂后端配置,低门槛快速搭建可用Web服务框架
- 环境纯净可控:基于uv管理环境,依赖隔离、安装极速,杜绝环境冲突
- 高可拓展性:分层架构清晰,可自由新增工具、业务、接口功能,适配长期迭代
- 双场景适配:支持开发热更新调试、生产打包部署,一套框架适配全流程
- 运行稳定:规避Nuitka打包闪退、资源丢失、浏览器弹窗失效等通用坑
九、整体总结
uv+FastAPI+Jinja2+Nuitka 是目前 Python 轻量化 Web 桌面应用 的最优通用框架方案。兼顾开发效率、运行稳定性、可打包性与可迭代性,无需复杂技术栈,以极简架构实现完整Web服务能力,适合绝大多数个人开发、小型项目、本地工具开发场景,可作为通用Python Web开发底座长期复用。
本文为通用框架实战教程,无业务绑定、可直接复刻复用,快速搭建属于自己的轻量化Python Web开发底座