Flask 快速入门

1. Flask 简介

1.1 什么是 Flask

Flask 是一个用 Python 编写的轻量级 Web 框架,被誉为 微框架。它提供基础功能,如路由、请求处理和模板引擎,但不强迫开发者使用特定库或工具,赋予开发人员高度的自由选择权,以满足不同项目的需求。

简单来说,Flask 帮助 Python 开发者快速构建 Web 应用,提供以下核心功能:

  • 路由: 将 URL 与对应的 Python 函数进行匹配,实现 URL 到函数的映射。
  • 请求处理: 处理来自用户的 HTTP 请求,例如获取请求参数、解析请求数据等,并将处理结果返回给用户。
  • 模板引擎: 使用 Jinja2 模板引擎动态渲染网页,将数据嵌入到 HTML 模板中,生成最终的 HTML 页面。

1.2 Flask 的优势

  • 轻量级和灵活: Flask 没有强迫性要求,允许开发者自由选择数据库、模板引擎和其他库,完全掌控项目的架构和组件选择。
  • 易于学习: Flask 的语法简洁直观,易于理解和掌握,即使是初学者也能快速上手。
  • 强大的社区支持: Flask 拥有庞大而活跃的社区,开发者可以轻松获取各种资源、教程、示例代码和帮助,解决开发中的问题。
  • 可扩展性: Flask 提供扩展机制,允许开发者通过添加扩展来扩展功能,例如数据库集成、用户认证、表单验证、邮件发送等,满足不同项目的需求。

1.3 Flask 的应用场景

Flask 适合以下应用场景:

  • 小型项目: 对于简单的网站或 API,Flask 提供快速开发和部署方案,节省时间和成本。
  • 原型开发: Flask 帮助开发者快速构建原型,验证想法的可行性,并进行快速迭代和修改。
  • 个性化需求: Flask 的灵活性满足定制化的 API、特定领域应用等需求,可以根据项目的特殊要求进行灵活调整和扩展。

一些使用 Flask 的知名应用:

  • Pinterest: 一家图片社交网站,使用 Flask 构建了其核心功能。
  • Lyft: 一家打车服务公司,使用 Flask 构建了其 API 和 Web 应用。
  • Twilio: 一家云通信平台,使用 Flask 构建了其 API 和管理界面。

1.4 Flask 的基本架构

Flask 的基本架构包括以下几个关键部分:

  1. WSGI 应用: Flask 应用本身是一个 WSGI 应用,负责接收 HTTP 请求并生成响应。
  2. 路由: 使用 @app.route 装饰器将 URL 与 Python 函数进行绑定,实现 URL 到函数的映射。
  3. 请求处理: Flask 提供 request 对象,用于获取 HTTP 请求信息,例如请求方法、请求参数、请求头等。
  4. 模板引擎: Flask 默认使用 Jinja2 模板引擎,用于渲染动态网页。
  5. 响应生成: Flask 使用 render_template 函数渲染模板,或使用 make_response 函数创建响应对象,并返回给用户。

了解这些基本架构有助于理解 Flask 的工作原理,以及如何使用 Flask 构建 Web 应用。

2. 快速上手

2.1 安装 Flask

使用 pip 安装 Flask:

bash 复制代码
pip install Flask

2.2 创建第一个 Flask 应用

创建名为 app.py 的文件,并添加以下代码:

python 复制代码
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello, Flask!'

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

代码解释:

  • from flask import Flask: 导入 Flask 库。
  • app = Flask(__name__): 创建一个 Flask 应用实例,__name__ 表示当前模块名,用于指定应用的根目录。
  • @app.route('/'): 定义一个路由,将根路径 /index 函数关联。
  • def index():: 定义一个函数,返回一个字符串 "Hello, Flask!"。
  • if __name__ == '__main__':: 确保代码只在直接运行脚本时执行,而不是被其他模块导入时执行。
  • app.run(debug=True): 运行 Flask 应用,开启调试模式。

2.3 运行 Flask 应用

在终端中运行以下命令:

bash 复制代码
python app.py

打开浏览器,访问 http://127.0.0.1:5000/,你将看到 "Hello, Flask!" 的输出。

2.4 使用路由

路由用于将 URL 与 Python 函数进行匹配。在上面的代码中,@app.route('/') 定义了一个路由,将根路径 /index 函数关联。

你可以定义多个路由,例如:

python 复制代码
@app.route('/about')
def about():
    return 'This is the about page.'

@app.route('/contact')
def contact():
    return 'This is the contact page.'

访问 http://127.0.0.1:5000/abouthttp://127.0.0.1:5000/contact 将分别显示 "This is the about page." 和 "This is the contact page."。

2.5 处理 HTTP 请求方法

Flask 可以区分不同的 HTTP 请求方法,例如 GETPOSTPUTDELETE 等。

可以使用 methods 参数来指定允许的 HTTP 请求方法:

python 复制代码
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return 'Login page'
    elif request.method == 'POST':
        # 处理 POST 请求
        return 'Login successful'

代码解释:

  • methods=['GET', 'POST']: 允许使用 GETPOST 请求方法访问 /login 路由。
  • request.method: 获取当前请求方法。

访问 http://127.0.0.1:5000/login 将显示 "Login page",使用 POST 请求则会显示 "Login successful"。

3. 模板渲染

模板渲染是将数据动态插入到 HTML 页面中,生成最终的 HTML 内容,Flask 使用 Jinja2 模板引擎来实现模板渲染。

3.1 Jinja2 模板引擎

Jinja2 是一个功能强大的模板引擎,它提供了一套语法来定义模板,并支持变量、循环、条件语句等功能。

3.2 使用模板渲染页面

  1. 创建模板文件

    在应用的根目录下创建 templates 目录,并将模板文件放在该目录下。例如,创建一个名为 index.html 的模板文件:

    html 复制代码
    <!DOCTYPE html>
    <html>
    <head>
        <title>My Flask App</title>
    </head>
    <body>
        <h1>Hello, {{ name }}!</h1>
    </body>
    </html>
  2. 使用 render_template() 函数渲染模板

    在视图函数中使用 render_template() 函数渲染模板,并将数据传递到模板中。

    python 复制代码
    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        name = 'World'
        return render_template('index.html', name=name)
    
    if __name__ == '__main__':
        app.run(debug=True)

    这段代码将 index.html 模板渲染,并传递 name 变量的值到模板中,最终生成的 HTML 内容为:

    html 复制代码
    <!DOCTYPE html>
    <html>
    <head>
        <title>My Flask App</title>
    </head>
    <body>
        <h1>Hello, World!</h1>
    </body>
    </html>

3.3 传递数据到模板

render_template() 函数中,可以使用关键字参数将数据传递到模板中。

传递单个变量:

python 复制代码
return render_template('index.html', name='World')

传递多个变量:

python 复制代码
return render_template('index.html', name='World', age=25)

传递列表:

python 复制代码
names = ['Alice', 'Bob', 'Charlie']
return render_template('index.html', names=names)

传递字典:

python 复制代码
user = {'name': 'Alice', 'age': 25}


return render_template('index.html', user=user)

3.4 模板继承

Jinja2 支持模板继承,允许你定义一个基础模板,并在其他模板中继承该基础模板。

基础模板 (base.html):

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Flask App{% endblock %}</title>
</head>
<body>
    <header>
        <h1>Welcome to My Flask App</h1>
    </header>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer>
        <p>&copy; 2023 My Flask App</p>
    </footer>
</body>
</html>

继承模板 (index.html):

html 复制代码
{% extends 'base.html' %}

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

{% block content %}
<h2>Hello, {{ name }}!</h2>
{% endblock %}

在继承模板中,可以使用 {% block %} 标签定义可覆盖的区域,并使用 {% extends %} 标签继承基础模板。

3.5 模板中的控制语句

Jinja2 支持在模板中使用控制语句,例如循环和条件语句。

循环语句:

html 复制代码
<ul>
    {% for name in names %}
    <li>{{ name }}</li>
    {% endfor %}
</ul>

条件语句:

html 复制代码
{% if user.is_authenticated %}
    <p>Welcome, {{ user.name }}!</p>
{% else %}
    <p>Please log in.</p>
{% endif %}

4. 数据库集成

Flask 通过集成 SQLAlchemy 等数据库 ORM 库,实现与数据库的交互。

4.1 安装 SQLAlchemy

使用 pip 安装 Flask-SQLAlchemy 扩展:

bash 复制代码
pip install Flask-SQLAlchemy

4.2 配置数据库

在应用的配置中添加数据库连接字符串,例如使用 SQLite 数据库:

python 复制代码
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mydatabase.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

4.3 定义模型

使用 SQLAlchemy 定义数据库模型,例如用户模型:

python 复制代码
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)

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)

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

代码解释:

  • db = SQLAlchemy(app): 创建一个 SQLAlchemy 实例,并绑定到 Flask 应用。
  • class User(db.Model): 定义一个用户模型,继承自 db.Model
  • id = db.Column(db.Integer, primary_key=True): 定义 id 列,作为主键。
  • username = db.Column(db.String(80), unique=True, nullable=False): 定义 username 列,字符串类型,必须唯一且非空。
  • email = db.Column(db.String(120), unique=True, nullable=False): 定义 email 列,字符串类型,必须唯一且非空。

4.4 创建数据库

在交互式 Python 解释器中运行以下命令,创建数据库和表:

python 复制代码
>>> from app import db
>>> db.create_all()

4.5 操作数据库

插入数据:

python 复制代码
user = User(username='Alice', email='alice@example.com')
db.session.add(user)
db.session.commit()

查询数据:

python 复制代码
users = User.query.all()
print(users)

更新数据:

python 复制代码
user = User.query.filter_by(username='Alice').first()
user.email = 'alice@newdomain.com'
db.session.commit()

删除数据:

python 复制代码
user = User.query.filter_by(username='Alice').first()
db.session.delete(user)
db.session.commit()

4.6 处理数据库关系

SQLAlchemy 支持处理一对多、多对多等复杂关系,例如定义一对多关系:

父模型:

python 复制代码
class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False)
    books = db.relationship('Book', backref='author', lazy=True)

子模型:

python 复制代码
class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'), nullable=False)

代码解释:

  • db.relationship('Book', backref='author', lazy=True): 在 Author 模型中定义一个关系属性 books,表示与 Book 模型的一对多关系。
  • db.ForeignKey('author.id'): 在 Book 模型中定义外键 author_id,指向 Author 模型的 id 列。

5. 表单处理

Flask-WTF 是一个集成 WTForms 的 Flask 扩展,用于处理表单创建、验证和错误处理。

5.1 安装 Flask-WTF

使用 pip 安装 Flask-WTF 扩展:

bash 复制代码
pip install Flask-WTF

5.2 配置 Flask-WTF

在应用的配置中添加 CSRF 保护的密钥:

python 复制代码
app.config['SECRET_KEY'] = 'your_secret_key'

5.3 定义表单

使用 Flask-WTF 定义一个登录表单:

python 复制代码
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Login')

代码解释:

  • FlaskForm: 表单基类。
  • StringField: 文本输入框。
  • PasswordField: 密码输入框。
  • SubmitField: 提交按钮。
  • DataRequired: 验证器,确保字段不为空。

5.4 渲染表单

在视图函数中创建表单实例,并在模板中渲染表单。

视图函数:

python 复制代码
@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        # 处理登录逻辑
        return 'Login successful'
    return render_template('login.html', form=form)

模板文件 (login.html):

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>Login</title>
</head>
<body>
    <form method="POST">
        {{ form.hidden_tag() }}
        <p>
            {{ form.username.label }}<br>
            {{ form.username(size=32) }}<br>
            {% for error in form.username.errors %}
                <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </p>
        <p>
            {{ form.password.label }}<br>
            {{ form.password(size=32) }}<br>
            {% for error in form.password.errors %}
                <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </p>
        <p>{{ form.submit() }}</p>
    </form>
</body>
</html>

代码解释:

  • form.validate_on_submit(): 检查表单是否通过验证。
  • {``{ form.hidden_tag() }}: 渲染 CSRF 保护的隐藏标签。
  • {``{ form.username.label }}: 渲染表单字段的标签。
  • {``{ form.username(size=32) }}: 渲染表单字段的输入框。
  • {% for error in form.username.errors %}: 渲染验证错误信息。

5.5 表单验证

在表单定义中添加验证器,例如 Email 验证器:

python 复制代码
from wtforms.validators import Email

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Login')

代码解释:

  • Email(): 验证器,确保字段是有效的电子邮件地址。

5.6 自定义验证器

可以定义自定义验证器,并在表单定义中使用:

python 复制代码
from wtforms.validators import ValidationError

def custom_validator(form, field):
    if field.data != 'expected_value':
        raise ValidationError('Invalid value')

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[

DataRequired(), custom_validator])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Login')

代码解释:

  • custom_validator(form, field): 自定义验证器函数,检查字段值是否为预期值。
  • raise ValidationError('Invalid value'): 抛出验证错误。

6. 用户认证

Flask-Login 是一个用户会话管理扩展,用于处理用户登录、注销和会话管理。

6.1 安装 Flask-Login

使用 pip 安装 Flask-Login 扩展:

bash 复制代码
pip install Flask-Login

6.2 配置 Flask-Login

在应用中初始化 Flask-Login,并定义用户加载函数:

python 复制代码
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user

login_manager = LoginManager(app)
login_manager.login_view = 'login'

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

代码解释:

  • LoginManager(app): 创建一个 LoginManager 实例,并绑定到 Flask 应用。
  • login_manager.login_view = 'login': 设置登录视图的端点。
  • @login_manager.user_loader: 定义用户加载函数,根据用户 ID 加载用户对象。

6.3 定义用户模型

用户模型需要继承 UserMixin,并实现用户加载函数:

python 复制代码
class User(UserMixin, 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)
    password = db.Column(db.String(128), nullable=False)

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

代码解释:

  • UserMixin: 提供用户会话管理所需的方法和属性。

6.4 用户登录

在视图函数中处理用户登录:

python 复制代码
@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.password == form.password.data:
            login_user(user)
            return 'Login successful'
    return render_template('login.html', form=form)

代码解释:

  • User.query.filter_by(username=form.username.data).first(): 根据用户名查询用户。
  • login_user(user): 登录用户,创建用户会话。

6.5 保护视图

使用 @login_required 装饰器保护需要登录访问的视图:

python 复制代码
@app.route('/dashboard')
@login_required
def dashboard():
    return f'Welcome, {current_user.username}!'

代码解释:

  • @login_required: 确保只有登录用户才能访问该视图。
  • current_user: 获取当前登录的用户对象。

6.6 用户注销

在视图函数中处理用户注销:

python 复制代码
@app.route('/logout')
@login_required
def logout():
    logout_user()
    return 'You have been logged out.'

代码解释:

  • logout_user(): 注销用户,结束用户会话。
相关推荐
邹霍梁@开源软件GoodERP20 分钟前
《手札·数转篇》中小制造企业的信息化升级:MES系统的价值与应用
python·开源·制造
星星点点洲1 小时前
【SpringBoot实现全局API限频】 最佳实践
java·spring boot·后端
华梦岚1 小时前
F#语言的学习路线
开发语言·后端·golang
虾球xz2 小时前
游戏引擎学习第92天
python·学习·游戏引擎
lllsure2 小时前
【快速入门】SpringMVC
java·后端·spring·mvc
AuGuSt_812 小时前
【已解决】lxml.etree.ParserError: Document is empty
爬虫·python
九亿AI算法优化工作室&2 小时前
KOA优化最近邻分类预测matlab
人工智能·python·机器学习·matlab·分类·数据挖掘·回归
程序员东min3 小时前
Python:凯撒密码
python·算法
梅清瑶3 小时前
Powershell语言的数据库编程
开发语言·后端·golang
是十一月末3 小时前
深度学习之神经网络框架搭建及模型优化
人工智能·pytorch·python·深度学习·神经网络