Python-web开发之Flask框架入门

Python Web 开发之 Flask 框架入门

一、Flask 简介

Flask 是一个基于 Python 的轻量级 Web 框架,由 Armin Ronacher 开发。它的设计哲学是微框架(Micro Framework)——核心保持简洁,功能通过扩展实现。

核心特点:

  • 轻量:核心代码精简,不绑定数据库、表单验证等组件
  • 灵活:可自由选择 ORM、模板引擎等组件
  • 易学:API 直观,上手快
  • Jinja2 模板:内置强大的模板引擎
  • Werkzeug WSGI:基于成熟的 WSGI 工具库
  • 扩展丰富:社区提供大量高质量扩展

安装:

pip install flask

二、第一个 Flask 应用

from flask import Flask

app = Flask(__name__)

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

if __name__ == "__main__":
    app.run(debug=True)

运行:

python app.py

访问 http://127.0.0.1:5000 即可看到页面。

app.run() 常用参数:

参数说明默认值
host监听地址127.0.0.1
port监听端口5000
debug开启调试模式(热重载 + 详细错误页)False

三、路由

3.1 基本路由

@app.route("/about")
def about():
    return "About Page"

@app.route("/contact")
def contact():
    return "Contact Page"

3.2 变量规则

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

# 指定类型
@app.route("/post/<int:post_id>")
def show_post(post_id):
    return f"Post ID: {post_id}"

@app.route("/price/<float:price>")
def show_price(price):
    return f"Price: {price}"

# 路径类型
@app.route("/file/<path:filename>")
def show_file(filename):
    return f"File: {filename}"

支持的类型转换器:

转换器说明
string默认,接受不含 / 的字符串
int整数
float浮点数
path/ 的字符串
uuidUUID 字符串

3.3 HTTP 方法

from flask import request

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "GET":
        return "Login Page"
    elif request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")
        return f"Login: {username}"

3.4 构造 URL

from flask import url_for

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

# 在视图函数或模板中使用
url_for("profile", username="alice")
# 输出: /user/alice

url_for 的优势:自动处理特殊字符和转义,修改路由规则时无需到处改 URL。

四、请求与响应

4.1 Request 对象

from flask import request

@app.route("/search")
def search():
    # URL 参数: /search?q=flask&page=1
    keyword = request.args.get("q")
    page = request.args.get("page", 1, type=int)

    # 请求头
    user_agent = request.headers.get("User-Agent")

    # 客户端 IP
    ip = request.remote_addr

    # 请求方法
    method = request.method

    return f"Search: {keyword}, Page: {page}"

4.2 处理表单与 JSON

@app.route("/api/data", methods=["POST"])
def handle_data():
    # 表单数据 (application/x-www-form-urlencoded / multipart)
    name = request.form.get("name")

    # JSON 数据 (application/json)
    json_data = request.get_json()
    title = json_data.get("title")

    # 原始请求体
    raw_data = request.data

    return {"status": "ok", "name": name}

4.3 Response 对象

from flask import jsonify, make_response

@app.route("/api/info")
def info():
    # 返回 JSON
    return jsonify({"version": "1.0", "name": "myapp"})

@app.route("/download")
def download():
    # 自定义响应
    response = make_response("Hello World")
    response.headers["Content-Type"] = "text/plain"
    response.headers["X-Custom"] = "value"
    response.set_cookie("session_id", "abc123")
    return response

@app.route("/redirect-demo")
def redirect_demo():
    from flask import redirect
    return redirect("/about")

五、模板引擎(Jinja2)

5.1 渲染模板

项目结构:

myapp/
├── app.py
└── templates/
    ├── base.html
    ├── index.html
    └── user.html
from flask import render_template

@app.route("/")
def index():
    return render_template("index.html", title="首页", items=["Apple", "Banana"])

5.2 模板语法

<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>
<!-- index.html -->
{% extends "base.html" %}

{% block title %}{{ title }}{% endblock %}

{% block content %}
    <h1>{{ title }}</h1>
    <ul>
    {% for item in items %}
        <li>{{ item }}</li>
    {% endfor %}
    </ul>
{% endblock %}

5.3 常用模板功能

<!-- 条件判断 -->
{% if user %}
    <p>欢迎, {{ user.name }}</p>
{% else %}
    <p>请登录</p>
{% endif %}

<!-- 循环 -->
{% for post in posts %}
    <h2>{{ post.title }}</h2>
{% else %}
    <p>暂无文章</p>
{% endfor %}

<!-- 过滤器 -->
<p>{{ content | truncate(100) }}</p>
<p>{{ date | datetimeformat("%Y-%m-%d") }}</p>
<p>{{ name | upper }}</p>
<p>{{ content | safe }}</p>  {# 不转义 HTML #}

<!-- 自定义过滤器 -->
{{ price | round(2) }}

5.4 自定义过滤器

@app.template_filter("reverse")
def reverse_filter(s):
    return s[::-1]

# 模板中使用: {{ "hello" | reverse }}  输出 olleh

六、会话管理

6.1 Cookie

from flask import make_response, request

@app.route("/set-cookie")
def set_cookie():
    resp = make_response("Cookie set")
    resp.set_cookie("username", "alice", max_age=3600, httponly=True)
    return resp

@app.route("/get-cookie")
def get_cookie():
    username = request.cookies.get("username")
    return f"Username: {username}"

6.2 Session

from flask import session

app.secret_key = "your-secret-key-here"  # 生产环境务必使用安全密钥

@app.route("/login", methods=["POST"])
def login():
    session["user_id"] = 42
    session["username"] = "alice"
    return "Login success"

@app.route("/profile")
def profile():
    user_id = session.get("user_id")
    if not user_id:
        return "Please login", 401
    return f"User ID: {user_id}"

@app.route("/logout")
def logout():
    session.clear()
    return "Logged out"

七、蓝图(Blueprint)——模块化开发

蓝图用于将应用拆分为多个模块,适合中大型项目。

7.1 项目结构

myapp/
├── app.py
├── auth/
│   ├── __init__.py
│   └── routes.py
├── blog/
│   ├── __init__.py
│   └── routes.py
└── templates/

7.2 定义蓝图

# auth/routes.py
from flask import Blueprint

auth_bp = Blueprint("auth", __name__, url_prefix="/auth")

@auth_bp.route("/login")
def login():
    return "Login Page"

@auth_bp.route("/register")
def register():
    return "Register Page"
# blog/routes.py
from flask import Blueprint

blog_bp = Blueprint("blog", __name__, url_prefix="/blog")

@blog_bp.route("/")
def index():
    return "Blog Index"

@blog_bp.route("/<int:post_id>")
def show_post(post_id):
    return f"Post: {post_id}"

7.3 注册蓝图

# app.py
from flask import Flask
from auth.routes import auth_bp
from blog.routes import blog_bp

app = Flask(__name__)
app.secret_key = "your-secret-key"

app.register_blueprint(auth_bp)
app.register_blueprint(blog_bp)

八、数据库集成(Flask-SQLAlchemy)

8.1 安装与配置

pip install flask-sqlalchemy
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

db = SQLAlchemy(app)

8.2 定义模型

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

    def __repr__(self):
        return f"<User {self.username}>"

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    content = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

8.3 增删改查

# 创建表
with app.app_context():
    db.create_all()

# 新增
user = User(username="alice", email="alice@example.com")
db.session.add(user)
db.session.commit()

# 查询
user = User.query.filter_by(username="alice").first()
users = User.query.all()
user = User.query.get(1)

# 修改
user.email = "new@example.com"
db.session.commit()

# 删除
db.session.delete(user)
db.session.commit()

九、表单处理(Flask-WTF)

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

app.config["SECRET_KEY"] = "your-secret-key"

class LoginForm(FlaskForm):
    username = StringField("Username", validators=[DataRequired(), Length(min=3, max=20)])
    email = StringField("Email", validators=[DataRequired(), Email()])
    password = PasswordField("Password", validators=[DataRequired(), Length(min=6)])
    submit = SubmitField("Login")

视图函数:

@app.route("/login", methods=["GET", "POST"])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        # 处理登录逻辑
        return f"Welcome, {form.username.data}"
    return render_template("login.html", form=form)

模板:

<form method="POST">
    {{ form.hidden_tag() }}
    <div>
        {{ form.username.label }}
        {{ form.username() }}
        {% for error in form.username.errors %}
            <span style="color:red">{{ error }}</span>
        {% endfor %}
    </div>
    <div>
        {{ form.password.label }}
        {{ form.password() }}
    </div>
    <div>{{ form.submit() }}</div>
</form>

十、错误处理

@app.errorhandler(404)
def not_found(error):
    return render_template("404.html"), 404

@app.errorhandler(500)
def server_error(error):
    return render_template("500.html"), 500

自定义异常:

class NotFoundError(Exception):
    pass

@app.errorhandler(NotFoundError)
def handle_not_found(error):
    return jsonify({"error": str(error)}), 404

十一、中间件与钩子

Flask 提供了请求生命周期中的钩子函数:

@app.before_request
def before_request():
    """每个请求前执行"""
    print(f"Request: {request.path}")

@app.after_request
def after_request(response):
    """每个请求后执行,可以修改响应"""
    response.headers["X-Request-ID"] = "abc123"
    return response

@app.teardown_request
def teardown_request(exception):
    """请求结束后执行(无论是否异常)"""
    print("Request finished")

@app.context_processor
def inject_globals():
    """向所有模板注入变量"""
    return {"site_name": "MyApp"}

十二、RESTful API 开发

12.1 返回 JSON

@app.route("/api/users", methods=["GET"])
def get_users():
    users = User.query.all()
    return jsonify([{"id": u.id, "name": u.username} for u in users])

@app.route("/api/users", methods=["POST"])
def create_user():
    data = request.get_json()
    if not data or "username" not in data:
        return jsonify({"error": "Username is required"}), 400
    user = User(username=data["username"])
    db.session.add(user)
    db.session.commit()
    return jsonify({"id": user.id, "username": user.username}), 201

@app.route("/api/users/<int:user_id>", methods=["PUT"])
def update_user(user_id):
    user = User.query.get_or_404(user_id)
    data = request.get_json()
    user.username = data.get("username", user.username)
    db.session.commit()
    return jsonify({"id": user.id, "username": user.username})

@app.route("/api/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
    user = User.query.get_or_404(user_id)
    db.session.delete(user)
    db.session.commit()
    return "", 204

12.2 使用 Flask-RESTful

pip install flask-restful
from flask_restful import Resource, Api

api = Api(app)

class UserResource(Resource):
    def get(self, user_id):
        user = User.query.get_or_404(user_id)
        return {"id": user.id, "username": user.username}

    def delete(self, user_id):
        user = User.query.get_or_404(user_id)
        db.session.delete(user)
        db.session.commit()
        return "", 204

api.add_resource(UserResource, "/api/users/<int:user_id>")

十三、部署

13.1 生产环境 WSGI 服务器

Flask 内置服务器不适合生产环境,推荐使用 Gunicorn:

pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:8000 "app:app"

参数说明:

  • -w 4:4 个 worker 进程
  • -b 0.0.0.0:8000:监听地址和端口

13.2 配置管理

# config.py
class Config:
    DEBUG = False
    SECRET_KEY = "prod-secret-key"
    SQLALCHEMY_DATABASE_URI = "postgresql://user:pass@localhost/db"

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = "sqlite:///dev.db"

class TestingConfig(Config):
    TESTING = True
    SQLALCHEMY_DATABASE_URI = "sqlite:///test.db"
# app.py
app.config.from_object("config.DevelopmentConfig")
# 或从环境变量
app.config.from_envvar("APP_SETTINGS")

十四、常用扩展一览

扩展用途
Flask-SQLAlchemyORM 数据库操作
Flask-Migrate数据库迁移(Alembic)
Flask-WTF表单验证
Flask-Login用户认证
Flask-RESTfulRESTful API
Flask-JWT-ExtendedJWT 认证
Flask-CORS跨域支持
Flask-Caching缓存
Flask-Mail邮件发送
Flask-DebugToolbar调试工具栏
Flask-Limiter接口限流
Flask-Admin后台管理界面

十五、总结

Flask 的核心优势在于简洁与灵活

  • 小项目:单文件即可快速搭建
  • 中项目:通过蓝图实现模块化
  • 大项目:配合扩展可以覆盖认证、ORM、API、缓存等全套需求

学习路径建议:

路由与视图 → 模板渲染 → 请求与响应 → 表单处理
    → 数据库集成 → 蓝图模块化 → 认证授权 → RESTful API → 部署
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值