这是个 python 的库

安装:

pip install Flask

from flask import Flask    //导入flask类
app = Flask(__name__)     
//创建实例‘app’,__name__是特殊变量,直接执行是__main__,被导入时模块名
//用来Flask是构造函数,传递这个变量是为了让Flask应用能找到这个文件
@app.route('/')       //装饰器,里面那个是url,'/'就是指网页根目录,该目录下加载该文件
def hello_world():
    return 'Hello, World!'
if __name__ == '__main__':     //在不是被导入的情况下执行debug
    app.run(debug=True)       //run方法,启动内置的开发服务器,参数表示同时启动调试

# 基本概念

路由:指定在特定 url 执行特定函数

@app.route('/')

视图函数:视图函数是处理请求并返回响应的 Python 函数。它们通常接收请求对象作为参数,并返回响应对象。

//需要导入request类
@app.route('/greet/<name>')
def greet(name):
    return f'Hello, {name}!'

请求对象:请求对象(request)包含了客户端发送的请求信息

//需要导入request类
@app.route('/submit', methods=['POST'])
def submit():
    username = request.form.get('username') //获取POST请求的对应字段
    return f'Hello, {username}!'

响应对象:响应对象包含了发送给客户端的响应信息,如状态码、响应头、响应体等。

//需要导入make_response类
@app.route('/custom_response')
def custom_response():
    response = make_response('This is a custom response!') //创建自定义响应对象
    response.headers['X-Custom-Header'] = 'Value' //创建响应头
    return response

模板:Flask 使用 Jinja2 模板引擎来渲染 HTML 模板。模板允许你将 Python 代码嵌入到 HTML 中,从而动态生成网页。

//需要导入render_template类
@app.route('/hello/<name>')
def hello(name):
    return render_template('hello.html', name=name)
//后面那个是传递给模板的变量,注意模板要在templates文件夹中
<h1>Hello, !</h1>    <--模板中使用参数-->

应用工厂:应用工厂是一个 Python 函数,它创建并返回一个 Flask 应用实例。这允许你配置和初始化你的应用,并且可以创建多个应用实例。

from flask import Flask
def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config_name)    //这个方法从指定对象加载配置
    from . import routes     //从当前包中导入模块routes.py
    app.register_blueprint(routes.bp)   //把其中的蓝图注册到该应用,模块化开发用
    return app

配置对象:有一个配置对象,你可以使用它来设置各种配置选项,如数据库连接字符串、调试模式等。

//上面的config_name
class Config:
    DEBUG = True
    SECRET_KEY = 'mysecretkey'  //密钥,加密会话用
    SQLALCHEMY_DATABASE_URI = 'sqlite:///mydatabase.db'  //数据库url
    STATIC_FOLDER = 'static'     //静态文件存储路径
	TEMPLATE_FOLDER = 'templates'    //蓝图存储路径
//这些玩意儿可以Flask(__name__,xxx)来指定。

蓝图:一个组织代码的方式,它允许你将相关的视图函数、模板和静态文件组织在一起,并且可以在多个应用中重用。

//需要导入Blueprint
bp = Blueprint('main', __name__)  //蓝图名+当前模块名
@bp.route('/')
def home():
    return 'Home Page'
from flask import Flask
from .routes import bp as main_bp  
//从当前包的 routes.py 模块里导入 bp 对象,并将其重命名为 main_bp。
//包是可以嵌套的..表示父包,可以认为包是一个存储模块的文件夹(所以用.或者..实际上等同于用相对路径)
def create_app():
    app = Flask(__name__)
    app.register_blueprint(main_bp)
    return app

静态文件:静态文件是不会被服务器端执行的文件,如 CSS、JavaScript 和图片文件。

<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
{% raw %}
//回去static目录找那个css文件
//这个通常是被导入的模板里的
//将静态文件放在 static 文件夹中,Flask 会自动提供服务(如果你没改)

扩展:有其他插件,难说~~

会话:存储用户信息,用户浏览应用时可以记住他们的状态。

就是 session,存储在 cookie

这里 session 对象用于存取对话数据

from flask import session
#可以使用 Python 内置的 secrets 模块生成一个强随机性的密钥
#import secrets; print(secrets.token_hex())
app.secret_key = 'your_secret_key_here'
@app.route('/set_session/<username>')
def set_session(username):
    session['username'] = username  //把变量username的值存储在会话中,键为username
    return f'Session set for {username}'
@app.route('/get_session')
def get_session():
    username = session.get('username')  //读取刚刚那个键的值
    return f'Hello, {username}!' if username else 'No session data'

Flask 的会话默认是永久的,但可以通过设置 session.permanent = True 来明确指定,并且可以通过 app.permanent_session_lifetime 来设置会话的过期时间。

错误处理:可以定义错误处理函数。

@app.errorhandler(404)
def page_not_found(e):
    return 'Page not found', 404
@app.errorhandler(500)
def internal_server_error(e):
    return 'Internal server error', 500

# 一个玩意儿

from flask import Flask, session, redirect, url_for, render_template_string
app = Flask(__name__)
app.secret_key = 'your_secret_key'
@app.route('/')    //定义首页路由
def index():        
    username = session.get('username')
    if username:
        return f'Hello, {username}!'
    else:
        return 'You are not logged in.'
@app.route('/login/<username>')   //定义登录路由
def login(username):
    session['username'] = username
    return redirect(url_for('index'))
@app.route('/logout')    //定义注销路由
def logout():
    session.pop('username', None)   //移除username键
    return redirect(url_for('index'))   //重定向回首页
if __name__ == '__main__':
    app.run(debug=True)

# 项目结构

my_flask_app/
│
├── app.py
└── requirements.txt
my_flask_app/
│
├── app/
│   ├── __init__.py
│   ├── routes.py
│   └── models.py
│
├── config.py
├── requirements.txt
└── run.py
my_flask_app/
│
├── app/                       //包含主要代码
│   ├── __init__.py    //3.0+版本不强制有,初始化Flask应用和配置扩展
│   ├── routes/                //应用路由和视图函数,这里用一个包代替上面的一个模块
│   │   ├── __init__.py         
│   │   ├── main.py             //主模块路由
│   │   └── auth.py             //认证相关路由
│   ├── models/               //数据库相关
│   │   ├── __init__.py
│   │   └── user.py                 //用户模型
│   ├── templates/             //存储HTML模板
│   │   ├── layout.html
│   │   └── home.html
│   └── static/
│       ├── css/
│       └── js/
│
├── config.py
├── requirements.txt       //列出依赖库
├── migrations/              //数据库迁移文件
│   └── ...
└── run.py                   //用于启动Flask应用

目录咯~

run.py 示例

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

route.py 示例

from flask import Blueprint
bp = Blueprint('main', __name__)
@bp.route('/')
def home():
    return 'Hello, World!'

_init_.py 示例

from flask import Flask
def create_app():
    app = Flask(__name__)
    app.config.from_object('config.Config')
    from . import routes
    app.register_blueprint(routes.bp)
    return app

# flask 路由

# 动态部分

@app.route('/greet/<name>')   
//这样可以将这一部分当做参数传给函数,比如:
def greet(name):
    return f'Hello, {name}!'

# 路由规则

路由规则支持不同类型的参数和匹配规则

字符串(默认),整数(<int:name>),浮点数(<float:value>),路径(<path:name>)

@app.route('/user/<int:user_id>')   //这样就不会全部都当作内容
def user_profile(user_id):
    return f'User ID: {user_id}'
@app.route('/files/<path:filename>')
def serve_file(filename):
    return f'Serving file: {filename}'

# 请求方法

@app.route('/submit', methods=['POST'])

# 路由转换器

还是那仨

@app.route('/items/<int:item_id>/details')

# 路由函数返回

通过视图函数(基本等同,只是路由函数要 url 映射)可以返回:

1742454735654

# 路由优先级

按照定义顺序

# 视图函数

# 接受数据

@app.route('/greet/<name>')    #url
@app.route('/submit', methods=['POST'])   #POST
def submit():
    username = request.form.get('username')
    return f'Form submitted by {username}!'
@app.route('/search')   #GET
def search():
    query = request.args.get('query')   //获取 GET 请求中的查询参数query
    return f'Search results for: {query}'

# 返回响应

return 'This is a simple message.'
return render_template('hello.html', name=name)  //记得导入render_template
def api_data():    //要导入jsonify
    data = {'key': 'value','key2':'value2'}
    return jsonify(data) 
//自动序列化,将 Python 数据类型(如字典、列表、字符串等,但不是全部)转换为 JSON 格式
//会自动设置Content—Type,支持多参数,自动合并为一个json对象
比如:
    return jsonify(
        message="Hello, World!",
        status=200,
        data=[1, 2, 3, 4]
    )

还可以用来:

设置状态码

return jsonify({"error": "Not Found"}), 404

返回自定义响应头

def custom_response():
    response = Response('Custom response with headers', status=200) 
    #创建自定义响应对象
    response.headers['X-Custom-Header'] = 'Value'
    return response

# 处理请求和响应

视图函数可以访问请求对象

使用 request 对象来获取请求的信息,使用 make_response 来创建自定义响应

def info():
    user_agent = request.headers.get('User-Agent')  //有点规律,我说命名
    return f'Your user agent is {user_agent}'
def custom_header():
    response = make_response('Response with custom header')
    response.headers['X-Custom-Header'] = 'Value'
    return response

# 处理错误

@app.route('/divide/<int:x>/<int:y>')
def divide(x, y):
    try:
        result = x / y
        return f'Result: {result}'
    except ZeroDivisionError:
        return 'Error: Division by zero', 400  //当然,状态码,可自定义
    //可以返回jsonify格式:
    return jsonify({
            'error': 'Division by zero',
            'message': 'The divisor cannot be zero.'
        }), 400
结构化响应:
def error_response(message, status_code):
    return jsonify({
        'error': {
            'message': message,
            'status_code': status_code
        }
    }), status_code
使用时:
return error_response('Invalid email format', 400, 'INVALID_EMAIL')
全局错误处理:
@app.errorhandler(404)  //定义处理404的函数
def not_found(error):
    return 'Page not found', 404

# 视图函数的装饰器

  • @app.before_request :在每个请求处理之前运行的函数。
  • @app.after_request :在每个请求处理之后运行的函数。
  • @app.teardown_request :在请求结束后运行的函数,用于清理工作。

# 视图函数返回的状态码

指定状态码(就上面那个):

return 'Everything is OK', 200

返回带状态码的对象:

return Response('An error occurred', status=500)

# 模板渲染

# 创建

{{ title }}{{ name }} 是模板占位符,将在渲染时被替换成实际的值

return render_template('index.html', title='Welcome Page', name='John Doe') //可以传入对象

# 继承

基础模板:

<title>{% block title %}My Website{% endblock %}</title> 
  <main>
        {% block content %}{% endblock %}   可替换区域
  </main>

子模板:

{% raw %}
{% extends "base.html" %}  //继承基础模板
{% block title %}Home Page{% endblock %}  //重写替换区域的内容
{% block content %}

Welcome to the Home Page!

Content goes here.

{% endblock %} {% raw %}

# 控制结构

{% if user %}
{% else %}
{% endif %}
{% for item in items %}
{% endfor %}

# 过滤器

处理变量用

{{ name|capitalize }}:将 name 变量的值首字母大写。

{{ price|round(2) }}:将 price 变量的值四舍五入到小数点后两位。

# 可能有用的

字符串处理

过滤器 功能描述 示例输入 输出结果
lower 转换为小写 "Hello" "hello"
upper 转换为大写 "world" "WORLD"
title 每个单词首字母大写 "hello world" "Hello World"
trim 去除前后空格 " flask " "flask"
striptags 去除 HTML/XML 标签 "Hello Flask" "Hello Flask"
truncate 截断字符串(超出长度后追加省略号) "long text here" (length=5) "long..."
replace(a, b) 替换字符串中的子串 "hello", "h", "j" "jello"
safe 标记为安全内容(不转义 HTML) "Hello Flask" 渲染为 Flask
# 数值操作
过滤器 功能描述 示例输入 输出结果
round 四舍五入 3.14159 3
int 转换为整数 "42" 42
float 转换为浮点数 "3.14" 3.14
format 格式化数值 1000, "0,.2f" "1,000.00"
default 设置默认值(变量不存在时使用) undefined_var, "N/A" "N/A"
# 日期时间
过滤器 功能描述 示例输入(Python datetime 对象) 输出结果
datetimeformat 格式化日期时间 now(), "%Y-%m-%d %H:%M" "2023-10-01 14:30"
date 提取日期部分 now() "2023-10-01"
time 提取时间部分 now() "14:30:45"
timedelta 计算时间差 start_date, end_date "3 days, 2 hours"
# 列表 / 字典操作
过滤器 功能描述 示例输入 输出结果
length 获取列表 / 字符串长度 [1, 2, 3] 3
sort 对列表排序 [3, 1, 2] [1, 2, 3]
reverse 反转列表 [1, 2, 3] [3, 2, 1]
join 连接列表元素 ["a", "b"], "-" "a-b"
keys 获取字典的键列表 {"a": 1, "b": 2} ["a", "b"]
values 获取字典的值列表 {"a": 1, "b": 2} [1, 2]
# 逻辑判断
过滤器 功能描述 示例输入 输出结果
if 条件判断 user.is_authenticated 根据条件渲染内容
default 变量不存在时使用默认值 username, "Guest" "Guest" (若 username 未定义)
none 判断是否为 None value truefalse
defined 判断变量是否存在 undefined_var false
# 其他实用过滤器
过滤器 功能描述 示例输入 输出结果
pprint 格式化输出(用于调试) {"a": 1, "b": 2} 美观缩进的 JSON 格式
markdown 将 Markdown 转换为 HTML "# Hello\n**Flask**" 渲染后的 HTML 内容
urlencode 对 URL 进行编码 "https://example.com?q=test" 编码后的字符串
regex_replace 使用正则表达式替换 "a1b2c3", "[0-9]", "" "abc"
# 链式调用示例
{{ "  hello world  "|trim|title|replace(" ", "-") }}
<!-- 输出:"Hello-World" -->
# 八。自定义过滤器

在 Flask 中可以注册自定义过滤器:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]
<!-- 模板中使用 -->
<!--swig18-->"olleh"

# 宏和模板包含

将在一个 html 文件中插入另一个的内容

# 创建宏

{% raw %}
{% macro render_item(item) %}

{{ item.title }}

{{ item.description }}

{% endmacro %}
{% raw %}
{% raw %}
{% from "macros.html" import render_item %}  //导入宏
{% for item in items %}
{{ render_item(item) }}   //用宏渲染每个item
{% endfor %}
{% raw %}

# 模板上下文

传递的参数可以直接用

# 表单处理

获取就是上面的 request.form.get('name')

[Flask-WTF 表单]( Flask 表单处理 | 菜鸟教程 ),用于防 CSRF, 可以进行表单验证。PS: 懒得看了~(这就是不学的理由?)

# 文件上传

通过 request.files 访问 。改一下编码类型(这真的需要自己改么......)

from flask import Flask, request, redirect, url_for
app = Flask(__name__)
app.secret_key = 'your_secret_key'
@app.route('/upload', methods=['POST'])
def upload():
    file = request.files.get('file')  
    if file:
        filename = file.filename  //获取原始文件名
        file.save(f'uploads/{filename}')
        return f'File uploaded successfully: {filename}'
    return 'No file uploaded'
if __name__ == '__main__':
    app.run(debug=True)

通过 request.files.get('file') 尝试从请求中获取名为 file 的文件对象。 request.files 是一个字典,存储了所有上传的文件

使用 file.save() 方法将文件保存到 uploads 目录下,文件名保持不变