Flask 3 保姆级教程(一):快速上手

一、创建项目

PyCharm 中新建项目

创建完成后会出现这么个项目

以下是代码解析:

python 复制代码
# 导入了 Flask 类
from flask import Flask

# 创建了一个 Flask web 应用的实例,并将其赋值给变量 app
# __name__ 是一个特殊的 Python 变量,它表示当前模块的名字。在大多数情况下,如果你直接运行这个脚本,__name__ 的值会是 '__main__'
# 传递 __name__ 给 Flask 的构造函数有助于 Flask 找到在哪里查找模板、静态文件等
app = Flask(__name__)


# 这是一个装饰器,它告诉 Flask 当用户访问应用的根 URL(例如 http://localhost:5000/)时,应该调用哪个函数来处理这个请求
@app.route('/')
# 定义函数,当 Flask 收到一个与 @app.route('/') 装饰器关联的 URL 请求时,它会调用这个函数
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    # 如果脚本是作为主程序运行(即 __name__ 的值是 '__main__'),那么这行代码会启动 Flask 的开发服务器,并监听默认的端口(通常是 5000)
    app.run()

运行脚本:

二、开启调试模式

为什么要开启调试模式

  1. 如果开启了DEBUG模式,那么在代码中如果抛出了异常,在浏览器的页面中可以看到具体的错误信息,以及具体的错误代码位置。方便开发者调试。

  2. 如果开启了DEBUG模式,那么以后在`Python'代码中修改了任何代码,只要按`ctrl+s``flask`就会自动的重新记载整个网站。不需要手动点击重新运行。

PyCharm 中开启 Debug 模式:

三、设置局域网内公开访问

开启这个选项后,所处同一局域网内的主机都能访问本机的项目

四、修改端口

如图

五、路由

5.1 添加路由

使用 route() 装饰器来把函数绑定到 URL:

python 复制代码
from flask import Flask


app = Flask(__name__)


@app.route('/')
def index():
    return '关注博主'


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


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

5.2 路由变量名规则

通过把 URL 的一部分标记为 <variable_name> 就可以在 URL 中添加变量。 标记的部分会作为关键字参数传递给函数

通过使用 <converter:variable_name> ,可以选择性的加上一个转换器,为变量指定规则

python 复制代码
from flask import Flask


app = Flask(__name__)


@app.route('/')
def index():
    return '关注博主'


# string(默认值)接受任何不包含斜杠的文本
@app.route('/hello')
def hello_world():
    return 'Hello World'


# int 接受正整数
@app.route('/post/<int:post_id>')
def show_post(post_id):
    return f'Post {post_id}'


# float 接受正浮点数
@app.route('/get/<float:get_id>')
def show_get(get_id):
    return f'Get {get_id}'


# path 类似 string ,但可以包含斜杠
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    return f'Subpath {subpath}'


# uuid 接受 UUID 字符串


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

5.3 使用函数构建 URL

url_for函数用于生成URL。它可以接受一个视图函数的名称作为参数,并返回与该视图函数关联的URL

python 复制代码
from flask import Flask, url_for

app = Flask(__name__)


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


@app.route('/user/<username>')
def user_profile(username):
    return f'Profile page of {username}'


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


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


# 创建一个测试请求上下文
# 测试请求上下文是为了模拟应用程序处理请求时的上下文环境。它允许我们在没有实际请求的情况下测试和调试路由函数的逻辑
with app.test_request_context():
    print(url_for('index'))  # 输出:/
    print(url_for('user_profile', username='john'))  # 输出:/user/john
    print(url_for('show_post', post_id=1))  # 输出:/post/1
    print(url_for('login'))  # 输出:/login

在上面的例子中,我们定义了几个路由函数,每个函数都有一个唯一的名称。通过url_for函数,我们可以根据这些函数的名称生成对应的URL

5.4 HTTP 方法

默认情况下,一个路由只回应 GET 请求。可以使用 route() 装饰器的 methods 参数来处理不同的 HTTP 方法

python 复制代码
from flask import Flask
from flask import request

app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # 处理POST请求的逻辑
        return 'Login success!'
    else:
        # 处理GET请求的逻辑
        return 'Please login'

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

上例中把路由的所有方法都放在同一个函数中,当每个方法都使用一些共同的数据时,这样是有用的

六、静态文件

Flask 也能做好这项工作。只要在您的包或模块旁边创建一个名为 static 的文件夹就行了。静态文件位于应用的 /static

python 复制代码
from flask import Flask, url_for

app = Flask(__name__)


@app.route('/')
def index():
    html_url = url_for('static', filename='index.html')
    return f'<a href="{html_url}">点击链接跳转</a>'


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

七、渲染模板

使用 render_template() 方法可以渲染模板,您只要提供模板名称和需要作为参数传递给模板的变量就行了

注意:Flask 会在 templates 文件夹内寻找模板

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>{{ name }}</h1>
    <h2>{{ age }}</h2>
    <h3>{{ sex }}</h3>
</body>
</html>
python 复制代码
from flask import Flask
from flask import render_template

app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html', name='Morant', age=19, sex='男')


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

八、请求数据

8.1 请求对象

首先,确保已经安装了Flask-WTF扩展包,它用于处理表单数据。可以使用pip install Flask-WTF进行安装

通过使用 method 属性可以操作当前请求方法,通过使用 form 属性处理表单数据(在 POST 或者 PUT 请求中传输的数据)

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Flask Form</title>
</head>
<body>
    <h1>Flask Form Example</h1>
    <form method="POST" action="/">
        {{ form.csrf_token }}
        {#    一行代码用于渲染表单对象的name字段及其对应的标签。form.name.label表示name字段的标签,form.name表示name字段的输入框。
        通过这个语法,模板引擎会将标签和输入框的HTML代码渲染到页面中,并在它们之间添加冒号进行分隔    #}
        {{ form.name.label }}: {{ form.name }}
        {{ form.submit }}
    </form>
</body>
</html>
python 复制代码
from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField

app = Flask(__name__)

# 设置了一个秘密密钥(SECRET_KEY)。秘密密钥是用于保护表单数据的重要配置
app.config['SECRET_KEY'] = 'secret_key'


# 继承自 FlaskForm 类
# FlaskForm类是wtforms库中Form类的子类,它扩展了Form类的功能,使其与Flask框架更好地集成
class MyForm(FlaskForm):
    # 创建一个名为Name的文本输入字段
    # 如果在HTML模板中使用{{ form.name.label }}来渲染该字段的标签,那么在浏览器中将显示一个带有文本Name的标签
    name = StringField('Name')

    # 创建一个标签为Submit的提交按钮字段
    # 在HTML模板中,可以使用{{ form.submit }}来渲染该字段,该字段将在浏览器中显示为一个提交按钮,文本为Submit
    submit = SubmitField('Submit')


@app.route('/', methods=['GET', 'POST'])
def index():
    form = MyForm()

    # validate_on_submit方法的作用是在表单提交的情况下进行验证
    if form.validate_on_submit():
        name = form.name.data
        return f'Hello, {name}!'

    # 这行代码将表单对象传递给模板,将模板渲染为最终的HTML响应,并将其返回给客户端
    return render_template('index.html', form=form)


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

8.2 文件上传

用 Flask 处理文件上传很容易,只要确保不要忘记在您的 HTML 表单中设置 enctype="multipart/form-data" 属性就可以了

补充知识点:

request.files是Flask框架中的一个特殊字典,用于存储通过表单上传的文件。它允许您在处理HTTP请求时访问上传的文件

当使用enctype="multipart/form-data"属性将表单的编码类型设置为多部分表单时,Flask将自动解析请求中的文件数据,并将它们存储在request.files字典中

request.files是一个可迭代的字典,其中键是表单中文件输入字段的名称,值是对应的文件对象。您可以通过键访问特定的文件对象,例如request.files['file']将返回名为file的文件对象

每个文件对象都有一些有用的属性,例如filename表示上传文件的原始文件名,stream表示文件的字节流,content_type表示文件的MIME类型等

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>File Upload</title>
</head>
<body>
    <h1>File Upload</h1>
    <form action="/upload" method="POST" enctype="multipart/form-data">
        <input type="file" name="file">
        <input type="submit" value="Upload">
    </form>
</body>
</html>
python 复制代码
from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import os

app = Flask(__name__)


@app.route('/')
def index():
    # 渲染模板
    return render_template('index.html')


@app.route('/upload', methods=['POST'])
def upload_file():
    # 检查请求中是否存在名为file的文件。它通过查看request.files字典来检查文件是否存在
    if 'file' not in request.files:
        return 'No file uploaded', 400

    file = request.files['file']

    if file.filename == '':
        return 'No file selected', 400

    if file:
        # secure_filename()函数是Flask框架中的一个实用函数,用于将文件名转换为安全的文件名格式
        filename = secure_filename(filename)
        # 使用file.save()方法将文件保存到服务器上的指定目录中
        file.save(os.path.join('uploads', filename))
        return 'File uploaded successfully'

    return 'File upload failed', 500


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

要访问 cookies ,可以使用 cookies 属性。可以使 用响应对象的 set_cookie 方法来设置 cookies

python 复制代码
from flask import Flask, request, make_response

app = Flask(__name__)


@app.route('/')
def index():
    # make_response('Cookie has been set!')是Flask框架中用于创建响应对象的函数
    # 它接受一个参数作为响应的内容,并返回一个包含该内容的响应对象
    # make_response('Cookie has been set!')创建了一个响应对象,响应的内容是字符串'Cookie has been set!'
    # 这个响应对象将被返回给客户端,作为对请求的响应
    resp = make_response('Cookie has been set!')
    # 设置 Cookie
    # 它接受两个参数,第一个参数是cookie的名称,第二个参数是cookie的值
    resp.set_cookie('username', 'Morant')
    return resp


@app.route('/get_cookie')
def get_cookie():
    # 从请求中获取cookie
    username = request.cookies.get('username')
    return f'Username: {username}'


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

九、重定向和错误

使用redirect()函数可以重定向。使用 abort() 可以更早退出请求,并返回错误代码

使用 erroehander() 装饰器可以定制出错页面

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <title>File Upload</title>
</head>
<body>
    <h1>重定向和自定义错误</h1>
</body>
</html>
python 复制代码
from flask import Flask, redirect, url_for, abort, render_template

app = Flask(__name__)


@app.route('/')
def index():
    # 重定向到另一个路由
    return redirect(url_for('hello'))


@app.route('/hello')
def hello():
    try:
        # 当num为0时,中止请求并返回状态码为400的错误响应
        num = 0
        result = 10 / num
        return f'10 divided by {num} is {result}'
    except ZeroDivisionError:
        # 捕获ZeroDivisionError异常并返回自定义的错误页面
        # 在这个例子中,return abort(400)会中止当前请求,并返回状态码为400的错误响应
        return abort(400)


# errorhandler(400)是Flask框架中用于处理指定状态码错误的装饰器
# 在这个例子中,@app.errorhandler(400)装饰器将下面的bad_request函数注册为处理状态码为400的错误的函数
@app.errorhandler(400)
# # 在这个例子中,bad_request函数会渲染一个名为index.html的模板,并返回该模板的响应。同时,使用状态码400来表示该响应
def bad_request(error):
    # 自定义400错误页面
    return render_template('index.html'), 400


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

十、响应

在Flask中,当视图函数返回一个值时,它会自动转换为一个响应对象,用于向客户端返回数据。根据返回值的不同类型,会有不同的转换规则:

  1. 如果返回值是一个响应对象,那么它会直接被返回。

  2. 如果返回值是一个字符串,那么它会被转换为一个带有默认参数的响应对象,包含该字符串作为响应主体,状态码为 200 OK,并且内容类型为text/html。

  3. 如果返回值是一个迭代器或生成器,那么它会被视为一个流式响应,将字符串或字节逐步返回给客户端。

  4. 如果返回值是一个字典或列表,Flask会调用`jsonify()`函数来创建一个响应对象,将字典或列表转换为JSON格式。

  5. 如果返回值是一个元组,那么元组中的项目可以提供额外的信息。元组必须至少包含一个项目,可以是`(response, status)`、`(response, headers)`或`(response, status, headers)`形式。其中,status的值会覆盖默认的状态码,headers是一个包含额外头部值的列表或字典。

  6. 如果以上规则都不适用,Flask会假设返回值是一个有效的WSGI应用程序,并将其转换为一个响应对象。

如果想在视图函数内部对响应对象进行更精细的控制,可以使用`make_response()`函数来创建响应对象,并对其进行设置。

10.1 返回响应对象

在这个例子中,视图函数response使用make_response()函数创建了一个自定义的响应对象resp。然后,它将该响应对象直接返回给客户端,Flask会将其发送给客户端作为响应

python 复制代码
from flask import Flask, make_response

app = Flask(__name__)


@app.route('/')
def response():
    # 创建自定义响应对象
    resp = make_response('Hello, Flask!')
    resp.headers['Content-Type'] = 'text/plain'
    resp.status_code = 200
    return resp


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

10.2 返回字符串

当访问根目录/时,视图函数hello返回一个字符串"Hello, Flask!"

Flask会自动将该字符串转换为一个响应对象,状态码为200 OK,内容类型为text/html,并将该字符串作为响应主体返回给客户端

python 复制代码
from flask import Flask

app = Flask(__name__)


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


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

10.3 返回迭代器或生成器

在这个例子中,视图函数stream返回一个迭代器/生成器generate。这个生成器通过使用yield关键字逐步生成响应的字符串内容。Flask会将每个生成的字符串立即发送给客户端,使得响应成为一个流式响应

python 复制代码
from flask import Flask

app = Flask(__name__)


@app.route('/')
def stream():
    def generate():
        yield 'Hello,'
        yield 'Flask!'

    return generate()


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

注意,生成器函数在第一次迭代时从函数体的开始处执行,然后在遇到第一个 yield 时暂停。在后续的迭代中,它从上一次暂停的 yield 语句之后继续执行,直到遇到下一个 yield,或者函数结束

10.4 返回字典或列表

当访问根目录/时,视图函数data返回一个字典{'name': 'John', 'age': 25}。Flask会自动调用jsonify()函数将字典转换为JSON格式,并创建一个响应对象来返回给客户端

python 复制代码
from flask import Flask, jsonify

app = Flask(__name__)


@app.route('/')
def data():
    return {'name': 'John', 'age': 25}


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

10.5 返回元组

当访问根目录/时,视图函数response返回一个元组('Hello, Flask!', 201)。元组中的第一个项目是响应主体,第二个项目是状态码。Flask会根据这个元组创建一个响应对象,并将其返回给客户端

python 复制代码
from flask import Flask

app = Flask(__name__)


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


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

10.6 使用 make_response() 函数

当访问根目录/时,视图函数response使用make_response()函数创建一个响应对象,并对其进行设置。在这个例子中,我们手动设置了响应主体、内容类型和状态码,并将该响应对象返回给客户端

python 复制代码
from flask import Flask, make_response

app = Flask(__name__)


@app.route('/')
def response():
    resp = make_response('Hello, Flask!')
    resp.headers['Content-Type'] = 'text/plain'
    resp.status_code = 200
    return resp


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

10.7 使用 jsonify() 函数

当视图函数返回一个字典或列表时,可以使用jsonify()函数将其转换为JSON格式,并创建一个响应对象返回给客户端。下面是一个使用jsonify()函数的案例:

python 复制代码
from flask import Flask, jsonify

app = Flask(__name__)


@app.route('/')
def data():
    data = {'name': 'John', 'age': 25}
    return jsonify(data)


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

十一、会话

使用会话之前您必须设置一个密钥

python 复制代码
from flask import Flask, session, redirect, url_for

app = Flask(__name__)
app.secret_key = 'your_secret_key'


@app.route('/')
def index():
    session['username'] = 'Morant'
    return 'Session is set!'


@app.route('/profile')
def profile():
    if 'username' in session:
        return f"Welcome, {session['username']}!"
    else:
        return redirect(url_for('index'))


@app.route('/logout')
def logout():
    session.pop('username', None)
    return 'Logged out!'


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

在这个例子中,我们首先设置了一个密钥secret_key,用于加密会话数据。然后,当访问根目录/时,视图函数index将用户名John存储在会话中的username键中。

接下来,当访问/profile时,视图函数profile将检查会话中是否存在username键。如果存在,它会欢迎用户,并显示用户名。否则,它会重定向到index视图函数来设置会话。

最后,当访问/logout时,视图函数logout会从会话中删除username键,以模拟用户注销操作。

通过使用会话,我们可以在不同的请求之间存储和访问数据,以实现用户认证、保持登录状态等功能。

十二、闪现消息

flash()函数用于在视图函数中闪现一条消息,这条消息可以在后续的请求中被读取和显示

get_flashed_messages()函数用于在模板中获取并操作这些消息

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <title>File Upload</title>
</head>
<body>
    <h1>Profile</h1>
    {% for message in messages %}
        <p>{{ message }}</p>
    {% endfor %}
</body>
</html>
python 复制代码
from flask import Flask, flash, redirect, render_template, url_for, get_flashed_messages

app = Flask(__name__)
app.secret_key = 'your_secret_key'


@app.route('/')
def index():
    flash('This is a flashed message!')
    return redirect(url_for('profile'))


@app.route('/profile')
def profile():
    messages = get_flashed_messages()
    return render_template('index.html', messages=messages)


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

在这个例子中,当访问根目录/时,视图函数index使用flash()函数来闪现一条消息,然后它会重定向到profile视图函数

profile视图函数中,使用get_flashed_messages()函数来获取闪现的消息,然后将这些消息传递给模板profile.html进行显示

在模板profile.html中,可以使用Jinja2的模板语法来遍历并显示消息

十三、日志

在这个例子中,我们定义了一个根路由/,当访问该路由时,会记录不同级别的日志信息。

通过app.logger.debug()app.logger.info()app.logger.warning()app.logger.error()函数,我们可以分别记录调试、信息、警告和错误级别的日志信息

python 复制代码
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    app.logger.debug('This is a debug message')
    app.logger.info('This is an info message')
    app.logger.warning('This is a warning message')
    app.logger.error('This is an error message')
    return 'Logged messages'

if __name__ == '__main__':
    app.run()
相关推荐
AI大模型-小华3 分钟前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
立心者01 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端
lipku2 小时前
数字人直播开源项目LiveStream
python·开源·数字人·数字人直播
AskHarries2 小时前
SEO 页面怎么生成
后端
阿童木写作2 小时前
Python实现亚马逊商品图批量智能抠图教程
人工智能·python
做前端的娜娜子2 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
爱吃牛肉的大老虎2 小时前
Rust对象之结构体,枚举,特性
开发语言·后端·rust
石榴2 小时前
NestJS 的请求到底经过了什么:装饰器、守卫、拦截器、管道与中间件如何配合
后端
小帅不太帅2 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek