Skip to content

Samsepik9/flask-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Flask Framework Demo

1.Flask简介

2.Flask安装

3.Flask基本使用


1. Flask简介

Flask是一个使用Python编写的轻量级Web应用框架。它基于Werkzeug WSGI工具箱和Jinja2模板引擎。Flask使用简单,易于扩展,适合小型项目和快速开发。

1.1 Flask特点

  • 轻量且高效:核心简洁,启动迅速,资源占用低
  • 灵活性:不强制特定项目结构或组件选择
  • 易于学习:API设计直观,学习曲线平缓
  • 可扩展性:通过丰富的扩展生态系统增强功能
  • 强大的路由系统:支持URL变量和HTTP方法
  • 内置开发服务器:便于本地测试和开发
  • RESTful支持:轻松构建符合REST规范的API

1.2 Flask vs Django

Flask和Django是Python Web开发中最流行的两个框架,它们各有优势:

特性 Flask Django
架构理念 微框架,灵活定制 全能框架,内置齐全
学习曲线 较低,容易上手 较高,概念较多
项目规模 适合小到中型项目 适合中到大型项目
自由度 高,可自由选择组件 低,遵循"Django方式"
数据库支持 通过扩展支持 ORM内置
管理后台 需要自行实现或使用扩展 内置强大的管理后台
PS: Markdown语法:表格对齐方式
使用 | 符号分隔列
使用 - 符号创建表头分隔线
列对齐可以通过在分隔线中使用 : 来实现:
:--- 左对齐
:---: 居中对齐
---: 右对齐


2. Flask安装

虚拟环境(venv)安装flask:

py -3.12 -m venv venv
.\venv\Scripts\activate(激活)
deactivate(退出)

# 设置清华源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 查看当前 pip 源
pip config list

pip install flask

pip install -e . 是将项目安装为可编辑模式(editable mode), 文件夹(包含__init__.py)会编译成一个包,代码中可绝对引用

3. Flask基本使用

3.1 Flask项目结构

my_flask_app/
│
├── app/
│   ├── __init__.py     # 应用工厂
│   ├── routes/         # 路由定义
│   │   ├── __init__.py
│   │   ├── main.py
│   │   └── auth.py
│   ├── models/         # 数据模型
│   │   ├── __init__.py
│   │   └── user.py
│   ├── templates/      # 模板文件
│   │   ├── layout.html
│   │   └── home.html
│   └── static/         # 静态文件
│       ├── css/
│       └── js/
│
├── config.py       # 配置文件
├── requirements.txt
├── migrations/
│   └── ...
└── run.py

3.2 Flask路由

Flask 路由是 Web 应用程序中将 URL 映射到 Python 函数的机制。

Flask 路由是 Flask 应用的核心部分,用于处理不同 URL 的请求,并将请求的处理委托给相应的视图函数。

  • 定义路由:使用 @app.route('/path') 装饰器定义 URL 和视图函数的映射。
  • 路由参数:通过动态部分在 URL 中传递参数。
  • 路由规则:使用类型转换器指定 URL 参数的类型。
  • 请求方法:指定允许的 HTTP 请求方法。
  • 路由函数返回:视图函数可以返回不同类型的响应。
  • 静态文件和模板:管理静态文件和动态渲染 HTML 模板。
  • 路由优先级:确保路由顺序正确,以避免意外的匹配结果。
from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return 'Welcome to the Home Page!'

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

参数匹配规则:
字符串(默认): 匹配任意字符串。
整数(<int:name>): 匹配整数值。
浮点数(<float:value>): 匹配浮点数值。
路径(<path:name>): 匹配任意字符,包括斜杠 /。

@app.route('/files/<path:filename>')
def serve_file(filename):
    return f'Serving file: {filename}'

路由转换

int: 匹配整数。 float: 匹配浮点数。 path: 匹配任意路径,包括斜杠。

@app.route('/items/<int:item_id>/details')
def item_details(item_id):
    return f'Item details for item ID: {item_id}'

<int:item_id>:将 URL 中的 item_id 转换为整数。

路由函数返回

视图函数可以返回多种类型的响应:

  • 字符串:返回纯文本响应。
  • HTML:返回 HTML 页面。
  • JSON:返回 JSON 数据。
  • Response 对象:自定义响应。
from flask import jsonify, Response

@app.route('/json')
def json_response():
    data = {'key': 'value'}
    return jsonify(data)

@app.route('/custom')
def custom_response():
    response = Response('Custom response with headers', status=200)
    response.headers['X-Custom-Header'] = 'Value'
    return response
jsonify(data):将字典转换为 JSON 响应。
Response('Custom response with headers', status=200):创建自定义响应对象。

静态文件和模板 静态文件(如 CSS、JavaScript、图片)可以通过 static 路由访问。模板文件则通过 templates 文件夹组织,用于渲染 HTML 页面。

<link rel="stylesheet" href="proxy.php?url=https%3A%2F%2Fgithub.com.%2F%7B%7B+url_for%28"static', filename='style.css') }}">

模板文件渲染:

from flask import render_template
@app.route('/hello/<name>')
def hello(name):
    return render_template('hello.html', name=name)
模板文件 (templates/hello.html):
<!DOCTYPE html>
<html>
<head>
    <title>Hello</title>
</head>
<body>
    <h1>Hello, {{ name }}!</h1>
</body>
</html>

路由优先级 Flask 按照定义的顺序匹配路由,第一个匹配成功的路由将被处理。确保更具体的路由放在更一般的路由之前

@app.route('/user/<int:user_id>')
def user_profile(user_id):
    return f'User ID: {user_id}'

@app.route('/user')
def user_list():
    return 'User List'

3.3 Flask视图函数

视图函数是 Flask 应用中的核心部分,它负责处理请求并生成响应。

视图函数与路由紧密结合,通过路由将 URL 映射到具体的视图函数。

  • 定义视图函数:视图函数是处理请求并返回响应的核心功能。
  • 接收请求数据:使用 request 对象获取 URL 参数、表单数据、查询参数等。
  • 返回响应:可以返回字符串、HTML、JSON 或自定义响应对象。
  • 处理请求和响应:使用 request 对象和 make_response 来处理请求和生成自定义响应。
  • 处理错误:视图函数内处理异常或使用 Flask 的错误处理机制。
  • 视图函数的装饰器:使用 @app.before_request、@app.after_request 等装饰器处理请求前后逻辑。 视图函数返回的状态码:可以指定 HTTP 状态码来表示请求的处理结果。

1.定义视图函数

视图函数是一个普通的 Python 函数,它接收请求并返回响应。视图函数通常与路由配合使用,通过装饰器将 URL 映射到视图函数。

2. 接收请求数据 视图函数可以接收不同类型的请求数据,包括 URL 参数、表单数据、查询参数等。

获取 URL 参数:

@app.route('/greet/<name>')
def greet(name):
    return f'Hello, {name}!'
<name> 是一个 URL 参数,传递到视图函数 greet。

获取表单数据:

from flask import request

@app.route('/submit', methods=['POST'])
def submit():
    username = request.form.get('username')
    return f'Form submitted by {username}!'
request.form.get('username'):获取 POST 请求中表单数据的 username 字段。

获取查询参数:

@app.route('/search')
def search():
    query = request.args.get('query')
    return f'Search results for: {query}'
request.args.get('query'):获取 GET 请求中的查询参数 query。

3. 返回响应

视图函数可以返回多种类型的响应,包括字符串、HTML、JSON、或自定义响应对象。

返回字符串:

@app.route('/message')
def message():
    return 'This is a simple message.'

返回 HTML 模板:

from flask import render_template

@app.route('/hello/<name>')
def hello(name):
    return render_template('hello.html', name=name)
render_template('hello.html', name=name):渲染 HTML 模板 hello.html,并将 name 变量传递给模板。

返回 JSON 数据:

from flask import jsonify

@app.route('/api/data')
def api_data():
    data = {'key': 'value'}
    return jsonify(data)
jsonify(data):将 Python 字典转换为 JSON 响应。

返回自定义响应对象:

from flask import Response

@app.route('/custom')
def custom_response():
    response = Response('Custom response with headers', status=200)
    response.headers['X-Custom-Header'] = 'Value'
    return response
Response('Custom response with headers', status=200):创建自定义响应对象,并设置响应头。

4. 处理请求和响应

视图函数可以访问请求对象,并根据请求数据生成响应。可以使用 request 对象来获取请求的信息,使用 make_response 来创建自定义响应。

使用 request 对象:

from flask import request

@app.route('/info')
def info():
    user_agent = request.headers.get('User-Agent')
    return f'Your user agent is {user_agent}'
request.headers.get('User-Agent'):获取请求头中的 User-Agent 信息。

使用 make_response:

from flask import make_response

@app.route('/header')
def custom_header():
    response = make_response('Response with custom header')
    response.headers['X-Custom-Header'] = 'Value'
    return response
make_response('Response with custom header'):创建响应对象并设置自定义头信息。

5. 处理错误

可以在视图函数中处理异常或错误,或者通过 Flask 提供的错误处理机制来处理应用中的错误。

在视图函数中处理错误:

@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
使用 try-except 语句处理除零错误,并返回自定义错误消息和状态码。

全局错误处理:

@app.errorhandler(404)
def not_found(error):
    return 'Page not found', 404
@app.errorhandler(404):定义处理 404 错误的函数。

6. 视图函数的装饰器

除了 @app.route,Flask 还支持其他装饰器,用于实现更复杂的功能。 示例: @app.before_request:在每个请求处理之前运行的函数。 @app.after_request:在每个请求处理之后运行的函数。 @app.teardown_request:在请求结束后运行的函数,用于清理工作。 示例装饰器使用:

@app.before_request
def before_request():
    print('Before request')

@app.after_request
def after_request(response):
    print('After request')
    return response

@app.teardown_request
def teardown_request(exception):
    print('Teardown request')

3.4 Flask模板渲染

模板是包含占位符的 HTML 文件。 Flask 使用 Jinja2 模板引擎来处理模板渲染。模板渲染允许你将动态内容插入到 HTML 页面中,使得应用能够生成动态的网页内容。

  • 创建模板:将 HTML 文件放在 templates 文件夹中,使用 Jinja2 占位符。
  • 渲染模板:使用 render_template 函数在视图函数中渲染模板。
  • 模板继承:创建基础模板,允许其他模板继承和扩展。
  • 控制结构:使用条件语句和循环在模板中控制逻辑。
  • 过滤器:使用过滤器格式化变量数据。
  • 宏和模板包含:创建和使用宏以及模板包含,提高模板的复用性。
  • 安全性:Jinja2 默认对模板变量进行自动转义以防止 XSS 攻击。
  • 模板上下文:将数据传递给模板,并在模板中使用这些数据。

1. 创建模板

模板文件通常放在项目的 templates 文件夹中。Flask 会自动从这个文件夹中查找模板文件。 templates/index.html 文件代码:

<!DOCTYPE html>
<html>
<head>
    <title>Welcome</title>
</head>
<body>
    <h1>{{ title }}</h1>
    <p>Hello, {{ name }}!</p>
</body>
</html>
{{ title }} 和 {{ name }} 是模板占位符,将在渲染时被替换成实际的值。

在视图函数中渲染模板: app.py 文件代码:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html', title='Welcome Page', name='John Doe')

if __name__ == '__main__':
    app.run(debug=True)
render_template('index.html', title='Welcome Page', name='John Doe'):渲染 index.html 模板,并将 title 和 name 变量传递给模板。

2. 模板继承 模板继承允许你创建一个基础模板,然后在其他模板中继承和扩展这个基础模板,避免重复的 HTML 代码。 创建基础模板:在 templates 文件夹中创建一个基础模板 base.html。 templates/base.html 示例:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
    <header>
        <h1>My Website</h1>
    </header>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer>
        <p>Footer content</p>
    </footer>
</body>
</html>

{% block title %}{% endblock %} 和 {% block content %}{% endblock %} 是定义的可替换区域。

创建子模板:在 templates 文件夹中创建一个子模板 index.html,继承 base.html。 templates/index.html 文件代码:

{% extends "base.html" %}

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

{% block content %}
<h2>Welcome to the Home Page!</h2>
<p>Content goes here.</p>
{% endblock %}
{% extends "base.html" %}:继承基础模板。

{% block title %} 和 {% block content %}:重写基础模板中的块内容

3. 控制结构 Jinja2 提供了多种控制结构,用于在模板中实现条件逻辑和循环。 条件语句:

{% if user %}
    <p>Welcome, {{ user }}!</p>
{% else %}
    <p>Please log in.</p>
{% endif %}

{% if user %}:检查 user 变量是否存在,如果存在,则显示欢迎消息,否则显示登录提示。

循环语句:

<ul>
{% for item in items %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

{% for item in items %}:遍历 items 列表,并为每个项生成一个

  • 元素。

    4. 过滤器 过滤器用于在模板中格式化和处理变量数据。

    <p>{{ name|capitalize }}</p>
    <p>{{ price|round(2) }}</p>
    

    {{ name|capitalize }}:将 name 变量的值首字母大写。 {{ price|round(2) }}:将 price 变量的值四舍五入到小数点后两位。

    5. 宏和模板包含 宏是可重用的模板片段。模板包含允许你在一个模板中插入另一个模板的内容。

    创建宏 templates/macros.html 代码文件:

    {% macro render_item(item) %}
        <div>
            <h3>{{ item.title }}</h3>
            <p>{{ item.description }}</p>
        </div>
    {% endmacro %}
    

    使用宏: templates/index.html 文件代码:

    {% from "macros.html" import render_item %}
    
    <h1>Items</h1>
    {% for item in items %}
        {{ render_item(item) }}
    {% endfor %}
    

    {% from "macros.html" import render_item %}:导入宏。 {{ render_item(item) }}:调用宏来渲染每个 item。

    6. 安全性 自动转义:Jinja2 默认会对模板中的变量进行自动转义,防止 XSS 攻击。

    {{ user_input }}

    {{ user_input }}:用户输入的内容会被自动转义,以避免恶意脚本的注入。

    7. 模板上下文 视图函数中传递的变量成为模板的上下文,这些变量可以在模板中直接使用。

    @app.route('/profile/<username>')
    def profile(username):
        user = {'name': username, 'age': 25}
        return render_template('profile.html', user=user)
    

    templates/profile.html 文件代码:

    <h1>{{ user.name }}</h1>
    <p>Age: {{ user.age }}</p>
    

    {{ user.name }} 和 {{ user.age }}:在模板中访问 user 变量的属性。


    3.5 Flask表单处理

    处理表单数据涉及到接收、验证和处理用户提交的表单。Flask 提供了基本的表单处理功能,但通常结合 Flask-WTF 扩展来简化表单操作和验证。

    • 基本表单处理:使用 request.form 获取表单数据。
    • 使用 Flask-WTF:结合 WTForms 进行表单处理和验证,简化表单操作。
    • 表单验证:使用验证器确保表单数据的有效性。
    • 文件上传:处理文件上传和保存文件。
    • CSRF 保护:确保表单免受跨站请求伪造攻击。

    创建 HTML 表单 templates/form.html 文件代码:

    <!DOCTYPE html>
    <html>
    <head>
        <title>Form Example</title>
    </head>
    <body>
        <form action="proxy.php?url=https%3A%2F%2Fgithub.com.%2Fsubmit" method="post">
            <label for="name">Name:</label>
            <input type="text" id="name" name="name">
            <br>
            <label for="email">Email:</label>
            <input type="email" id="email" name="email">
            <br>
            <input type="submit" value="Submit">
        </form>
    </body>
    </html>
    

    action="proxy.php?url=https%3A%2F%2Fgithub.com.%2Fsubmit":表单数据提交到 /submit 路径。 method="post":使用 POST 方法提交数据。

    处理表单数据 app.py 文件代码:

    from flask import Flask, render_template, request
    
    app = Flask(__name__)
    
    @app.route('/')
    def form():
        return render_template('form.html')
    
    @app.route('/submit', methods=['POST'])
    def submit():
        name = request.form.get('name')
        email = request.form.get('email')
        return f'Name: {name}, Email: {email}'
    
    if __name__ == '__main__':
        app.run(debug=True)
    request.form.get('name') 和 request.form.get('email'):获取提交的表单数据。
    
  • About

    personal learning flask

    Resources

    Stars

    Watchers

    Forks

    Releases

    No releases published

    Packages

     
     
     

    Contributors