搭建 Flask Web 应用编程环境

84 阅读5分钟
  • 这是一份简要的 Windows 下安装 Python+VSCode 的操作教程。
  • 主要面向基于 Flask 的 Web 开发入门。
  • 主要是命令,解释较少。

0. 安装步骤概览

  1. 准备 Python 环境
  2. 安装依赖
  3. 跑示例程序
  4. 安装与配置 VSCode

把数据库换成 MariaDB 是可选的第 5 步;修复和重装看第 6 步。

1. 准备 Python 环境

每种 Python 应用都会有一大堆依赖包,包之间有版本依赖。这一步准备一个特定的环境。

  • 如果今后准备练习多个项目,如基础Web开发、RAG开发、深度学习,选方案A。
  • 如果只准备做一个项目,如毕业设计项目,选方案B。

方案 A:Anaconda(多环境)

  • 从官网,点击 Windows 64-Bit Graphical Installer 的链接,下载 Anaconda。
  • 也可以下载更轻量的 Miniconda,用法基本一样,需要深度学习包(NumPy、Matplotlib、Pandas)另外装。
  • 双击后安装。
  • 开始菜单中从 Anaconda (anaconda3) 中找到 Anaconda Prompt。
conda create --name flask-web python=3.11 -y --override-channels -c https://mirrors.ustc.edu.cn/anaconda/pkgs/main/
conda activate flask-web
  • 第一行创建一个名为 flask-web 的环境,Web 开发专用,第二行切换到这个环境,而不污染默认的 base 环境。
  • 第一行命令中 python=3.11 指 Python 的版本(3.10 之前的版本 2026 年 10 月已经停止维护,3.11+ 都可以)。
  • --override-channels -c https://mirrors.ustc.edu.cn/anaconda/pkgs/main/ 是用国内源;但国内源有时本身也不稳定,如果官方源连得上可以不加。

下文“命令行”都是指这个环境的命令行,提示符前要有 (flask-web) 字样(如下),否则这一步没有装对。

(flask-web) C:\Users\xxx>

方案 B:venv (单项目)

  • 从Python 官网 下载 Python 安装包。
  • 下载后双击安装。
  • 安装后修改 PATH 环境变量,使系统能找到 python.exe。
  • 打开一个命令行窗口,切换到项目文件夹,执行以下命令:
cd your_project_dir
python -m venv .venv
.venv\Scripts\activate

2. 安装依赖

设置国内源,加速下载

命令行中输入

pip config set global.index-url https://mirrors.aliyun.com/pypi/simple

安装常用包

用记事本在项目文件夹(方案B)下创建一个文本文件 requirements.txt,里面内容为常用的依赖包:

Flask
Flask-SQLAlchemy
Flask-Migrate
Flask-Login
python-dotenv
Flask-WTF
email-validator
#waitress

命令行中运行

pip install -r requirements.txt

3. 跑示例程序

用记事本创建一个文本文件示例程序 app.py,内容见第7节。

首次运行前创建 SQLite 数据库表:

flask db init
flask db migrate
flask 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 停止。

4. 安装与配置 VSCode

  1. 官网下载 VSCode code.visualstudio.com/ 并安装

  2. 安装扩展 【Python(Microsoft)】

  3. Ctrl+Shift+P → Python: Select Interpreter → 选 flask-web 环境(或项目下的 .venv)

    • 如不确定 conda 装在哪:
      conda info --base
      
  4. 如 PowerShell 报“在此系统上禁止运行脚本”时,用管理员身份打开一个 Powershell 窗口, 执行下述命令:

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
    

    出现提示:

    执行策略更改
    执行策略可帮助你防止执行不信任的脚本。更改执行策略可能会产生安全风险,如 https:/go.microsoft.com/fwlink/?LinkID=135170
    中的 about_Execution_Policies 帮助主题所述。是否要更改执行策略?
    [Y] 是(Y)  [A] 全是(A)  [N] 否(N)  [L] 全否(L)  [S] 暂停(S)  [?] 帮助 (默认值为“N”):
    

    输入 A 回车。

5. 安装 MariaDB(免费 MySQL)数据库(可选)

Flask默认使用单文件数据库SQLite,如要安装生产级 MySQL 数据库,执行以下步骤:

  1. 下载MariaDB(社区版 MySQL):官方地址。
  2. 安装时设好 root 密码,如 abc123。
  3. 按装 Python 的 MySQL 驱动
    pip install pymysql
    
  4. 创建数据库:用 MariaDB 安装包自带的 HeidiSQL 程序创建,不用敲 SQL(安装时默认勾选,开始菜单里能找到)。
    1. 打开 HeidiSQL,点左下角 【新建】 创建一个会话:右侧用户 root,密码填安装时设的那个,如abc123,然后点右下角 【打开】 按钮。
    2. 左侧连接树里右键单击刚建好的会话 → 【创建新的(L)】 → 【数据库】。
    3. 名称填 flaskweb,字符校对选 utf8mb4_unicode_520_ci,点 【确定】。
  5. 创建一个 .env 文本文件,里面写入:
    DATABASE_URL=mysql+pymysql://root:你的密码@127.0.0.1:3306/flaskweb
    
    其中你的密码改成之前的密码,如 abc123。
  6. 重新建表:flask db upgrade 再跑一次即可。migrations/ 还在,不用再 init。

6. 修复和重建环境

遇到包冲突,如果可以确定某个包的问题,比如 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

7. 样例代码

点击展开Flask开发测试样例代码 app.py
import os

from dotenv import load_dotenv
from flask import Flask, jsonify, request
from flask_login import (LoginManager, UserMixin, current_user, 
    login_required, login_user, logout_user)
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.exc import SQLAlchemyError
from werkzeug.security import check_password_hash, generate_password_hash

load_dotenv()

db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()


class User(UserMixin, db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, nullable=False, index=True)
    password_hash = db.Column(db.String(255), nullable=False)

    def set_password(self, raw):
        ''' 保存密码哈希 '''
        self.password_hash = generate_password_hash(raw)

    def check_password(self, raw):
        return check_password_hash(self.password_hash, raw)


def create_app():
    app = Flask(__name__)
    app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev-secret-change-me')
    app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///app.db')

    db.init_app(app)
    migrate.init_app(app, db)
    login_manager.init_app(app)

    @login_manager.user_loader
    def load_user(user_id):
        return db.session.get(User, int(user_id))

    @login_manager.unauthorized_handler
    def unauthorized():
        return jsonify({'error': '未登录'}), 401

    @app.get('/')
    def index():
        state = {
            'status': 'ok',
            'user': current_user.username if current_user.is_authenticated else None,
        }
        try:
            state['users'] = db.session.query(User).count()
        except SQLAlchemyError:
            db.session.rollback()
            state['users'] = None
            state['hint'] = '数据表还没建,先执行 flask --app app db upgrade'
        return jsonify(state)

    @app.post('/register')
    def register():
        data = request.get_json(silent=True) or {}
        username = str(data.get('username') or '').strip()
        password = str(data.get('password') or '')
        if not username or not password:
            return jsonify({'error': '需要 username 和 password 两个字段'}), 400
        if db.session.query(User).filter_by(username=username).first():
            return jsonify({'error': '用户名已存在'}), 409

        user = User(username=username)
        user.set_password(password)
        db.session.add(user)
        db.session.commit()
        return jsonify({'id': user.id, 'username': user.username}), 201

    @app.post('/login')
    def login():
        data = request.get_json(silent=True) or {}
        username = str(data.get('username') or '').strip()
        password = str(data.get('password') or '')
        user = db.session.query(User).filter_by(username=username).first()
        if user is None or not user.check_password(password):
            return jsonify({'error': '用户名或密码不正确'}), 401
        login_user(user)
        return jsonify({'id': user.id, 'username': user.username})

    @app.post('/logout')
    @login_required
    def logout():
        logout_user()
        return jsonify({'status': '已登出'})

    @app.get('/profile')
    @login_required
    def profile():
        return jsonify({'id': current_user.id, 'username': current_user.username})

    return app


app = create_app()


if __name__ == '__main__':
    print('数据库  : {}'.format(app.config['SQLALCHEMY_DATABASE_URI']))
    app.run(port=5000, debug=True)
    # 生产环境服务器
    #from waitress import serve
    #serve(app, host='0.0.0.0', port=8080, threads=4)