首次提交
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# ============================================================
|
||||
# 使用说明:复制本文件为 .env,然后填入真实的配置值
|
||||
# 命令: cp .env.example .env
|
||||
# ⚠️ .env 文件已被 .gitignore 忽略,不会被提交到 Git
|
||||
# ============================================================
|
||||
|
||||
# Flask 会话签名密钥(生产环境必须替换为随机字符串)
|
||||
# 生成方式: python -c "import secrets; print(secrets.token_hex(32))"
|
||||
SECRET_KEY=change-me-to-random-string
|
||||
|
||||
# 数据库连接 URI
|
||||
# 格式: dialect+driver://username:password@host:port/database?params
|
||||
# 默认使用 SQLite 方便本地开发,零配置即可运行
|
||||
DATABASE_URL=sqlite:///app.db
|
||||
|
||||
# MySQL 示例(需安装 PyMySQL):
|
||||
# DATABASE_URL=mysql+pymysql://root:your_password@localhost:3306/mydb?charset=utf8mb4
|
||||
|
||||
# PostgreSQL 示例(需安装 psycopg2-binary):
|
||||
# DATABASE_URL=postgresql+psycopg2://user:your_password@localhost:5432/mydb
|
||||
|
||||
# 数据库连接池大小(仅生产环境生效,根据服务器内存调整)
|
||||
DB_POOL_SIZE=10
|
||||
+35
-161
@@ -1,176 +1,50 @@
|
||||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
# ==================== Python 运行时产物 ====================
|
||||
# 字节码缓存目录,每次运行自动生成,无需版本控制
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
# 虚拟环境目录(每个开发者本地创建,不纳入仓库)
|
||||
venv/
|
||||
env/
|
||||
.venv/
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
# ==================== Flask 框架产物 ====================
|
||||
# Flask 默认实例文件夹(存放 SQLite、日志等运行时文件)
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# UV
|
||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
#uv.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
# ==================== ⚠️ 安全相关(最重要) ====================
|
||||
# 环境变量文件:包含数据库密码、密钥等敏感信息,绝对禁止提交!
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
.env.*
|
||||
# 但保留示例文件,让新成员知道需要配置哪些变量
|
||||
!.env.example
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
# ==================== IDE 与操作系统 ====================
|
||||
.vscode/
|
||||
.idea/
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
# ==================== 数据库文件 ====================
|
||||
# SQLite 数据库文件是运行时生成的,不应纳入版本控制
|
||||
*.db
|
||||
*.sqlite3
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# Ruff stuff:
|
||||
.ruff_cache/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
# ==================== 测试与覆盖率 ====================
|
||||
htmlcov/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.pytest_cache/
|
||||
.tox/
|
||||
.nox/
|
||||
.cache/
|
||||
|
||||
# ==================== 构建/分发产物 ====================
|
||||
build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
*.egg
|
||||
@@ -1,19 +1,75 @@
|
||||
# flask_example
|
||||
|
||||
flask框架和连接数据库模板
|
||||
> 基于 Flask 3.x + SQLAlchemy 2.0 的生产级项目模板
|
||||
> 内置应用工厂、数据库迁移、安全配置和 CRUD 示例
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
```bash
|
||||
# 1. 克隆项目
|
||||
git clone <your-repo-url> && cd flask-db-template
|
||||
|
||||
# 2. 创建虚拟环境并安装依赖
|
||||
python -m venv venv
|
||||
source venv/bin/activate # macOS/Linux
|
||||
# venv\Scripts\activate # Windows
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 3. 配置环境变量(⚠️ 必须执行)
|
||||
cp .env.example .env
|
||||
# 编辑 .env,至少修改 SECRET_KEY 和 DATABASE_URL
|
||||
|
||||
# 4. 初始化数据库
|
||||
flask db init # 首次执行,生成 migrations/ 目录
|
||||
flask db migrate -m "init" # 生成迁移脚本
|
||||
flask db upgrade # 应用迁移到数据库
|
||||
|
||||
# 5. 启动开发服务器
|
||||
python run.py
|
||||
```
|
||||
my_flask_app/
|
||||
|
||||
## 📡 API 接口
|
||||
|
||||
| 方法 | 路径 | 说明 | 请求体 |
|
||||
|------|------|------|--------|
|
||||
| `POST` | `/api/users` | 创建用户 | `{"username":"test","email":"t@example.com"}` |
|
||||
| `GET` | `/api/users?page=1&per_page=20` | 分页查询用户 | - |
|
||||
|
||||
## ⚠️ 安全须知
|
||||
|
||||
- **永远不要**将 `.env` 提交到 Git(已在 `.gitignore` 中排除)
|
||||
- 生产部署使用 Gunicorn:`gunicorn -w 4 -b 0.0.0.0:8000 "run:app"`
|
||||
- 修改模型后**必须**执行 `flask db migrate` + `flask db upgrade`
|
||||
- `debug=True` 仅限开发环境,生产环境开启会导致源码泄露
|
||||
|
||||
## 📂 项目结构说明
|
||||
|
||||
```
|
||||
flask-db-template/
|
||||
├── app/
|
||||
│ ├── __init__.py # 应用工厂 & 扩展初始化
|
||||
│ ├── config.py # 配置文件
|
||||
│ ├── models/ # 数据模型
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── user.py
|
||||
│ └── routes/ # 蓝图/路由
|
||||
│ ├── __init__.py
|
||||
│ └── user.py
|
||||
├── migrations/ # 数据库迁移文件 (Flask-Migrate)
|
||||
├── .env # 环境变量(不要提交到Git)
|
||||
├── requirements.txt
|
||||
└── run.py # 启动入口
|
||||
```
|
||||
│ ├── __init__.py # 应用工厂:创建Flask实例并初始化扩展
|
||||
│ ├── config.py # 配置管理:集中管理所有环境变量和数据库配置
|
||||
│ ├── models/
|
||||
│ │ ├── __init__.py # 模型统一导出:确保迁移工具能发现所有表
|
||||
│ │ └── user.py # 用户模型:定义数据表结构和序列化方法
|
||||
│ └── routes/
|
||||
│ ├── __init__.py # 蓝图统一导出
|
||||
│ └── user.py # 用户API:包含完整的CRUD和异常处理
|
||||
├── migrations/ # 数据库迁移目录(由flask db init生成)
|
||||
│ └── .gitkeep # Git空目录占位符
|
||||
├── .env.example # 环境变量模板(不含真实密码,可安全提交)
|
||||
├── .gitignore # Git忽略规则(防止敏感文件和缓存被提交)
|
||||
├── README.md # 项目文档
|
||||
├── requirements.txt # Python依赖清单(锁定版本保证环境一致)
|
||||
└── run.py # 启动入口:开发环境启动脚本
|
||||
```
|
||||
|
||||
| 文件/目录 | 作用 |
|
||||
|-----------|------|
|
||||
| `app/__init__.py` | 应用工厂,创建 Flask 实例并初始化扩展 |
|
||||
| `app/config.py` | 集中配置管理,从环境变量读取敏感信息 |
|
||||
| `app/models/` | SQLAlchemy 数据模型定义 |
|
||||
| `app/routes/` | Blueprint 路由模块,按资源拆分 |
|
||||
| `migrations/` | Alembic 数据库迁移脚本 |
|
||||
| `.env.example` | 环境变量模板(安全提交到 Git) |
|
||||
| `run.py` | 开发环境启动入口 |
|
||||
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
应用工厂模块(Application Factory Pattern)
|
||||
- 延迟创建 Flask 实例,支持测试时传入不同配置
|
||||
- 扩展对象在模块顶层创建但不绑定 app,通过 init_app() 延迟绑定
|
||||
- 这种模式是 Flask 官方推荐的最佳实践,避免循环导入
|
||||
"""
|
||||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_migrate import Migrate
|
||||
from app.config import Config
|
||||
|
||||
# ✅ 扩展实例在工厂外部创建,不与任何 app 绑定
|
||||
# 这样可以在测试中创建多个 app 实例共享同一套扩展
|
||||
db = SQLAlchemy()
|
||||
migrate = Migrate()
|
||||
|
||||
|
||||
def create_app(config_class=Config):
|
||||
"""
|
||||
应用工厂函数
|
||||
:param config_class: 配置类,默认使用 Config,测试时可替换为 TestingConfig
|
||||
:return: 配置完成的 Flask 应用实例
|
||||
"""
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(config_class)
|
||||
|
||||
# 将扩展绑定到当前 app 实例
|
||||
db.init_app(app)
|
||||
migrate.init_app(app, db)
|
||||
|
||||
# 注册蓝图(放在这里避免循环导入:蓝图引用 db → db 在工厂中初始化)
|
||||
from app.routes.user import user_bp
|
||||
app.register_blueprint(user_bp, url_prefix='/api/users')
|
||||
|
||||
return app
|
||||
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
应用配置模块
|
||||
- 集中管理所有配置项,支持多环境切换
|
||||
- 通过 python-dotenv 自动加载 .env 文件中的环境变量
|
||||
- 敏感信息全部从环境变量读取,绝不硬编码
|
||||
"""
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# 自动加载项目根目录下的 .env 文件
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class Config:
|
||||
"""基础配置类(开发/生产通用)"""
|
||||
|
||||
# Flask 会话加密密钥,用于 cookie 签名和 CSRF 保护
|
||||
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-prod')
|
||||
|
||||
# 数据库连接字符串,优先读取环境变量,回退到本地 SQLite
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:///app.db')
|
||||
|
||||
# 关闭 SQLAlchemy 事件追踪,避免不必要的内存开销和警告
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
|
||||
# 是否打印 SQL 语句(开发调试时可设为 True,生产环境务必关闭)
|
||||
SQLALCHEMY_ECHO = False
|
||||
|
||||
# 数据库引擎高级选项(主要针对 MySQL/PostgreSQL 连接池)
|
||||
SQLALCHEMY_ENGINE_OPTIONS = {
|
||||
# 连接池常驻连接数
|
||||
'pool_size': int(os.environ.get('DB_POOL_SIZE', 10)),
|
||||
# 连接最大存活时间(秒),防止数据库端主动断开空闲连接
|
||||
'pool_recycle': 3600,
|
||||
# 每次从池中取出连接前先 ping 一下,避免拿到已断开的死连接
|
||||
'pool_pre_ping': True,
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
模型统一导出模块
|
||||
- Alembic(Flask-Migrate 底层)通过扫描此文件发现所有模型
|
||||
- 新增模型后必须在此处添加 import,否则 `flask db migrate` 无法检测到新表
|
||||
- __all__ 明确声明公开接口,避免意外导入内部模块
|
||||
"""
|
||||
from app.models.user import User
|
||||
|
||||
__all__ = ['User']
|
||||
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
用户数据模型
|
||||
- 定义 users 表结构、字段约束和索引
|
||||
- 提供 to_dict() 方法用于 API 响应序列化
|
||||
- 注意:不要在模型中直接 import Blueprint 或路由,避免循环导入
|
||||
"""
|
||||
from datetime import datetime
|
||||
from app import db
|
||||
|
||||
|
||||
class User(db.Model):
|
||||
"""用户表模型"""
|
||||
__tablename__ = 'users'
|
||||
|
||||
# 主键:自增整数,InnoDB 聚簇索引默认按主键排序
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
|
||||
# 用户名:唯一约束 + B-tree 索引,加速查询和去重校验
|
||||
username = db.Column(db.String(80), unique=True, nullable=False, index=True)
|
||||
|
||||
# 邮箱:唯一约束,业务层应额外做格式校验
|
||||
email = db.Column(db.String(120), unique=True, nullable=False)
|
||||
|
||||
# 创建时间:默认值为记录插入时的 UTC 时间
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
将模型实例序列化为字典
|
||||
- 用于 API JSON 响应,避免直接暴露内部字段(如密码哈希)
|
||||
- datetime 转为 ISO 8601 字符串,前端可直接解析
|
||||
"""
|
||||
return {
|
||||
'id': self.id,
|
||||
'username': self.username,
|
||||
'email': self.email,
|
||||
'created_at': self.created_at.isoformat(),
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
"""调试友好的字符串表示,在 Flask shell 和日志中显示"""
|
||||
return f'<User {self.username}>'
|
||||
@@ -0,0 +1,8 @@
|
||||
"""
|
||||
蓝图统一导出模块
|
||||
- 当蓝图数量增多时,在此集中管理,简化 __init__.py 中的注册逻辑
|
||||
- 新增蓝图后只需在此添加一行 import
|
||||
"""
|
||||
from app.routes.user import user_bp
|
||||
|
||||
__all__ = ['user_bp']
|
||||
@@ -0,0 +1,64 @@
|
||||
"""
|
||||
用户 API 路由模块
|
||||
- 使用 Blueprint 实现模块化路由,避免单文件膨胀
|
||||
- 包含参数校验、异常处理和分页查询的生产级实现
|
||||
- 所有数据库写操作均包裹在 try/except 中,失败时自动回滚
|
||||
"""
|
||||
from flask import Blueprint, request, jsonify
|
||||
from app import db
|
||||
from app.models.user import User
|
||||
|
||||
# 创建蓝图,名称用于 url_for() 反向解析,__name__ 用于定位模板/静态文件
|
||||
user_bp = Blueprint('user', __name__)
|
||||
|
||||
|
||||
@user_bp.route('', methods=['POST'])
|
||||
def create_user():
|
||||
"""
|
||||
创建新用户
|
||||
- POST /api/users
|
||||
- Body: {"username": "string", "email": "string"}
|
||||
- Returns: 201 + 用户JSON / 400 + 错误信息 / 500 + 服务器错误
|
||||
"""
|
||||
# silent=True 使得非 JSON 请求体返回 None 而非抛出 400 异常
|
||||
data = request.get_json(silent=True)
|
||||
|
||||
# ✅ 入参校验:永远不要信任客户端输入
|
||||
if not data or 'username' not in data or 'email' not in data:
|
||||
return jsonify({'error': 'Missing required fields: username, email'}), 400
|
||||
|
||||
try:
|
||||
user = User(username=data['username'], email=data['email'])
|
||||
db.session.add(user)
|
||||
# commit 同时完成 flush(发送SQL)和事务提交
|
||||
db.session.commit()
|
||||
return jsonify(user.to_dict()), 201
|
||||
except Exception as e:
|
||||
# ✅ 异常时必须回滚,否则后续请求复用该 session 会持续报错
|
||||
db.session.rollback()
|
||||
# 生产环境应记录日志而非直接返回异常详情,此处为模板演示
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
@user_bp.route('', methods=['GET'])
|
||||
def get_users():
|
||||
"""
|
||||
分页获取用户列表
|
||||
- GET /api/users?page=1&per_page=20
|
||||
- Returns: 分页结果 JSON,包含 items、total、pages、current_page
|
||||
"""
|
||||
# type=int 确保参数被转换为整数,非法值回退到默认值
|
||||
page = request.args.get('page', 1, type=int)
|
||||
per_page = request.args.get('per_page', 20, type=int)
|
||||
|
||||
# paginate() 自动处理 LIMIT/OFFSET,error_out=False 避免页码越界时抛异常
|
||||
pagination = User.query.order_by(User.created_at.desc()).paginate(
|
||||
page=page, per_page=per_page, error_out=False
|
||||
)
|
||||
|
||||
return jsonify({
|
||||
'items': [u.to_dict() for u in pagination.items],
|
||||
'total': pagination.total, # 总记录数
|
||||
'pages': pagination.pages, # 总页数
|
||||
'current_page': page, # 当前页码
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
# 此文件唯一作用:让 Git 跟踪 migrations/ 空目录
|
||||
# Git 不支持空目录,没有此文件则 clone 后缺少 migrations/ 目录
|
||||
# 执行 `flask db init` 后此文件会被实际迁移文件替代,可删除
|
||||
@@ -0,0 +1,17 @@
|
||||
# Flask 核心框架(3.x 支持异步和现代特性)
|
||||
Flask==3.0.0
|
||||
|
||||
# ORM 扩展:将数据库操作映射为 Python 对象
|
||||
Flask-SQLAlchemy==3.1.1
|
||||
|
||||
# 数据库迁移工具:基于 Alembic,自动追踪模型变更并生成迁移脚本
|
||||
Flask-Migrate==4.0.5
|
||||
|
||||
# 环境变量加载:从 .env 文件读取配置,避免硬编码敏感信息
|
||||
python-dotenv==1.0.0
|
||||
|
||||
# MySQL 驱动:纯 Python 实现,兼容性好(PostgreSQL 请替换为 psycopg2-binary)
|
||||
PyMySQL==1.1.0
|
||||
|
||||
# PyMySQL 加密依赖:支持 MySQL 8.0+ 的 caching_sha2_password 认证
|
||||
cryptography==41.0.7
|
||||
@@ -0,0 +1,20 @@
|
||||
"""
|
||||
开发环境启动入口
|
||||
- 仅在本地开发时使用,生产环境请用 Gunicorn/uWSGI
|
||||
- 启动前自动建表(仅限开发便利,生产环境必须使用 flask db upgrade)
|
||||
- debug=True 开启热重载和交互式调试器(⚠️ 生产环境严禁开启)
|
||||
"""
|
||||
from app import create_app, db
|
||||
|
||||
app = create_app()
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 在应用上下文中执行数据库操作
|
||||
with app.app_context():
|
||||
# ⚠️ create_all() 仅用于开发快速验证
|
||||
# 生产环境请使用: flask db migrate && flask db upgrade
|
||||
db.create_all()
|
||||
|
||||
# host='0.0.0.0' 允许外部访问(Docker/局域网调试需要)
|
||||
# 仅监听 127.0.0.1 则只允许本机访问
|
||||
app.run(debug=True, host='0.0.0.0', port=5000)
|
||||
Reference in New Issue
Block a user