- 安装步骤概览
- 准备 Python 环境
- 装依赖,跑一次自检
- 跑示例程序
- 接 VSCode
把数据库换成 MariaDB 是可选的第 5 步;修复和重装看第 7 步。
- 准备 Python 环境
方案 A:Anaconda(多环境)
conda create --name flask-web python=3.11 -y
conda activate flask-web
Python 版本推荐 3.11+。
方案 B:venv (单项目)
- 从官网 下载 Python。
- 安装后修改
PATH变量。 - 然后在项目文件夹执行以下命令:
python -m venv .venv
.venv\Scripts\activate
- 装依赖,跑自检
设置国内源,加速下载
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple
安装常用包
cd web-basic
pip install -r requirements.txt
requirements.txt:
Flask
Flask-SQLAlchemy
Flask-Migrate
Flask-Login
python-dotenv
Flask-WTF
email-validator
#waitress
- 跑示例程序
首次运行前建表:
flask --app app db init
flask --app app db migrate
flask --app app db upgrade
启动示例程序(见附录):
python app.py
用浏览器打开 http://127.0.0.1:5000/,看到 "users": 0 才算成功 —— 只看 status 不行,表没建时它也是 ok。
顺手再看一个受保护接口:http://127.0.0.1:5000/profile 返回 {"error": "未登录"},说明拦截生效。
按 Ctrl+C 停止。
- 接 VSCode
-
官网下载 VSCode code.visualstudio.com/ 并安装
-
装扩展 Python(Microsoft)
-
Ctrl+Shift+P→Python: Select Interpreter→ 选flask-web环境(或项目下的.venv)-
如不确定 conda 装在哪: ``` conda info --base
-
-
如 PowerShell 报“在此系统上禁止运行脚本”时,用管理员身份执行一次: ``` Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
-
装 MariaDB(免费 MySQL)数据库(可选)
如需将默认的 SQLite 升级为 MySQL 数据库:
-
下载安装:官方地址。安装时设好 root 密码,如
abc123。 -
装驱动``` pip install pymysql
-
建库:用 MariaDB 安装包自带的 HeidiSQL 建,不用敲 SQL(安装时默认勾选,开始菜单里能找到)。
- 打开 HeidiSQL,点左下角 新建 建会话:用户
root,密码填安装时设的那个,然后点右下角 打开 按钮。 - 左侧连接树里右键单击刚建好的会话 → 创建新的 → 数据库。
- 名称填
flaskweb,字符校对选utf8mb4_unicode_520_ci,点 确定。
- 打开 HeidiSQL,点左下角 新建 建会话:用户
-
改
.env: ``` DATABASE_URL=mysql+pymysql://root:你的密码@127.0.0.1:3306/flaskweb -
重新建表:
flask --app app db upgrade再跑一次即可。migrations/还在,不用再init。 -
样例代码
(略)
- 修复和重建环境
遇到包冲突,如果可以确定某个包的问题,比如 flask-socketio,可以试着重装这个包:
pip install --force-reinstall flask-socketio
实在修不了,重建
conda deactivate
conda env remove --name flask-web
conda create --name flask-web python=3.11 -y
conda activate flask-web
pip install -r requirements.txt
附:示例程序
<span>import</span> os
<span>from</span> dotenv <span>import</span> load_dotenv
<span>from</span> flask <span>import</span> Flask, jsonify, request
<span>from</span> flask_login <span>import</span> (LoginManager, UserMixin, current_user,
login_required, login_user, logout_user)
<span>from</span> flask_migrate <span>import</span> Migrate
<span>from</span> flask_sqlalchemy <span>import</span> SQLAlchemy
<span>from</span> sqlalchemy.exc <span>import</span> SQLAlchemyError
<span>from</span> werkzeug.security <span>import</span> check_password_hash, generate_password_hash
load_dotenv()
db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()
<span>class</span> <span>User</span>(UserMixin, db.Model):
__tablename__ = <span>'users'</span>
<span>id</span> = db.Column(db.Integer, primary_key=<span>True</span>)
username = db.Column(db.String(<span>64</span>), unique=<span>True</span>, nullable=<span>False</span>, index=<span>True</span>)
password_hash = db.Column(db.String(<span>255</span>), nullable=<span>False</span>)
<span>def</span> <span>set_password</span>(<span>self, raw</span>):
<span>''' 保存密码哈希 '''</span>
self.password_hash = generate_password_hash(raw)
<span>def</span> <span>check_password</span>(<span>self, raw</span>):
<span>return</span> check_password_hash(self.password_hash, raw)
<span>def</span> <span>create_app</span>():
app = Flask(__name__)
app.config[<span>'SECRET_KEY'</span>] = os.getenv(<span>'SECRET_KEY'</span>, <span>'dev-secret-change-me'</span>)
app.config[<span>'SQLALCHEMY_DATABASE_URI'</span>] = os.getenv(<span>'DATABASE_URL'</span>, <span>'sqlite:///app.db'</span>)
db.init_app(app)
migrate.init_app(app, db)
login_manager.init_app(app)
<span> @login_manager.user_loader</span>
<span>def</span> <span>load_user</span>(<span>user_id</span>):
<span>return</span> db.session.get(User, <span>int</span>(user_id))
<span> @login_manager.unauthorized_handler</span>
<span>def</span> <span>unauthorized</span>():
<span>return</span> jsonify({<span>'error'</span>: <span>'未登录'</span>}), <span>401</span>
<span> @app.get(<span><span>'/'</span></span>)</span>
<span>def</span> <span>index</span>():
state = {
<span>'status'</span>: <span>'ok'</span>,
<span>'user'</span>: current_user.username <span>if</span> current_user.is_authenticated <span>else</span> <span>None</span>,
}
<span>try</span>:
state[<span>'users'</span>] = db.session.query(User).count()
<span>except</span> SQLAlchemyError:
db.session.rollback()
state[<span>'users'</span>] = <span>None</span>
state[<span>'hint'</span>] = <span>'数据表还没建,先执行 flask --app app db upgrade'</span>
<span>return</span> jsonify(state)
<span> @app.post(<span><span>'/register'</span></span>)</span>
<span>def</span> <span>register</span>():
data = request.get_json(silent=<span>True</span>) <span>or</span> {}
username = <span>str</span>(data.get(<span>'username'</span>) <span>or</span> <span>''</span>).strip()
password = <span>str</span>(data.get(<span>'password'</span>) <span>or</span> <span>''</span>)
<span>if</span> <span>not</span> username <span>or</span> <span>not</span> password:
<span>return</span> jsonify({<span>'error'</span>: <span>'需要 username 和 password 两个字段'</span>}), <span>400</span>
<span>if</span> db.session.query(User).filter_by(username=username).first():
<span>return</span> jsonify({<span>'error'</span>: <span>'用户名已存在'</span>}), <span>409</span>
user = User(username=username)
user.set_password(password)
db.session.add(user)
db.session.commit()
<span>return</span> jsonify({<span>'id'</span>: user.<span>id</span>, <span>'username'</span>: user.username}), <span>201</span>
<span> @app.post(<span><span>'/login'</span></span>)</span>
<span>def</span> <span>login</span>():
data = request.get_json(silent=<span>True</span>) <span>or</span> {}
username = <span>str</span>(data.get(<span>'username'</span>) <span>or</span> <span>''</span>).strip()
password = <span>str</span>(data.get(<span>'password'</span>) <span>or</span> <span>''</span>)
user = db.session.query(User).filter_by(username=username).first()
<span>if</span> user <span>is</span> <span>None</span> <span>or</span> <span>not</span> user.check_password(password):
<span>return</span> jsonify({<span>'error'</span>: <span>'用户名或密码不正确'</span>}), <span>401</span>
login_user(user)
<span>return</span> jsonify({<span>'id'</span>: user.<span>id</span>, <span>'username'</span>: user.username})
<span> @app.post(<span><span>'/logout'</span></span>)</span>
<span> @login_required</span>
<span>def</span> <span>logout</span>():
logout_user()
<span>return</span> jsonify({<span>'status'</span>: <span>'已登出'</span>})
<span> @app.get(<span><span>'/profile'</span></span>)</span>
<span> @login_required</span>
<span>def</span> <span>profile</span>():
<span>return</span> jsonify({<span>'id'</span>: current_user.<span>id</span>, <span>'username'</span>: current_user.username})
<span>return</span> app
app = create_app()
<span>if</span> __name__ == <span>'__main__'</span>:
<span>print</span>(<span>'数据库 : {}'</span>.<span>format</span>(app.config[<span>'SQLALCHEMY_DATABASE_URI'</span>]))
app.run(port=<span>5000</span>, debug=<span>True</span>)
<span># 生产环境服务器</span>
<span>#from waitress import serve</span>
<span>#serve(app, host='0.0.0.0', port=8080, threads=4)</span>
纯命令式清单,跳过原理只给步骤,适合已有基础的开发者快速复现环境。遇到包冲突、多解释器切换或数据库升级时可直接照做,新手建议对照官方文档补齐细节。