Python Flask 快速入门:路由、模板、Jinja2、WTForms、SQLAlchemy

小飞兽 Python 5 次阅读 2026-07-24

Introduction

Flask 是 Python 最流行的轻量级 Web 框架。本文从最小的 Hello World 开始,详解 Flask 的路由、模板渲染、Jinja2 语法、WTForms 表单验证、SQLAlchemy ORM、以及 Flask 蓝图模块化开发。

---

最小 Flask 应用

pip install flask
# app.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, World!'

@app.route('/user/<name>')
def greet(name):
    return f'Hello, {name}!'

if __name__ == '__main__':
    app.run(debug=True, port=5000)

路由与变量规则

@app.route('/post/<int:post_id>')
def get_post(post_id):
    return f'Post ID: {post_id}'

@app.route('/user/<username>')
def profile(username):
    return f'User: {username}'

# HTTP 方法
@app.route('/submit', methods=['GET', 'POST'])
def submit():
    if request.method == 'POST':
        return 'Posted!'
    return 'Form'

模板渲染(Jinja2)

from flask import render_template, request

@app.route('/')
def index():
    articles = [
        {'title': 'Flask 入门', 'views': 100},
        {'title': 'Django vs Flask', 'views': 200},
    ]
    return render_template('index.html', articles=articles, title='首页')
<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
<h1>{{ title }}</h1>
{% for article in articles %}
<article>
    <h2>{{ article.title }}</h2>
    <span>阅读: {{ article.views }}</span>
</article>
{% endfor %}
</body>
</html>

Jinja2 常用语法

{# 注释 #}
{{ variable }}
{{ variable|default('默认值') }}
{{ variable|length }}
{{ "%.2f"|format(3.14159) }}
{% if user.is_admin %}
    管理员面板
{% elif user.is_active %}
    欢迎回来
{% else %}
    请登录
{% endif %}
{% for item in items %}{{ item }}{% endfor %}
{% macro render_field(field) %}
    {{ field.label }} {{ field(**kwargs) }}
{% endmacro %}

WTForms 表单验证

pip install flask-wtf
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email, Length

class LoginForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired(), Length(3, 20)])
    password = PasswordField('密码', validators=[DataRequired()])
    submit = SubmitField('登录')
@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data):
            login_user(user)
            return redirect(url_for('dashboard'))
    return render_template('login.html', form=form)
<form method="post">
    {{ form.hidden_tag() }}
    {{ form.username.label }} {{ form.username() }}
    {{ form.password.label }} {{ form.password() }}
    {{ form.submit() }}
</form>

SQLAlchemy ORM

pip install flask-sqlalchemy
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)
    posts = db.relationship('Post', backref='author', lazy=True)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200))
    content = db.Column(db.Text)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    created_at = db.Column(db.DateTime, default=db.func.now())

# 查询
users = User.query.filter_by(username='张三').first()
user_posts = Post.query.filter_by(user_id=user.id).order_by(Post.created_at.desc()).all()

蓝图(模块化)

# apps/auth.py
from flask import Blueprint
bp = Blueprint('auth', __name__, url_prefix='/auth')

@bp.route('/login')
def login(): return 'Login'

@bp.route('/logout')
def logout(): return 'Logout'

# app.py 注册
from apps.auth import bp as auth_bp
app.register_blueprint(auth_bp)

REST API

from flask import jsonify

@app.route('/api/posts')
def get_posts():
    posts = Post.query.order_by(Post.created_at.desc()).limit(20).all()
    return jsonify([{
        'id': p.id,
        'title': p.title,
        'content': p.content,
        'author': p.author.username,
        'created_at': p.created_at.isoformat()
    } for p in posts])

常见问题

Q1: Flask 跟 Django 怎么选?Flask 更轻量灵活,适合 API 和小项目。Django 全功能自带 ORM/Admin,适合企业应用。

Q2: 如何处理文件上传?from flask import request; file = request.files['file']; file.save('uploads/' + file.filename)。

Q3: Flask-SQLAlchemy 怎么防止 SQL 注入?SQLAlchemy 自动参数化查询,不用担心 SQL 注入。

延伸阅读

  • Flask-RESTful 快速 API 开发
  • Flask 单元测试
  • Flask + Docker 部署

---

作者:小马 | 绍大技术网 shaoda.net