Flask应用的基本组成部分、模板引擎Jinja2的使用、Flask-WTF、SQLAlchemy
创始人
2024-05-27 05:43:00
0

目录标题

      • 1. Flask应用的基本组成部分
        • 1.1 路由(Routing)
        • 1.2 视图函数(View Function)
        • 1.3 请求(Request)
        • 1.4 响应(Response)
      • 2. 模板引擎Jinja2的使用
        • 2.1 入门案例
        • 2.2 条件判断
        • 2.3 循环遍历
        • 2.4 过滤器
        • 2.5 宏
        • 2.6 定义临时变量
        • 2.7 定义模板
      • 3. Flask-WTF表单处理和验证
        • 3.1 安装 Flask-WTF
        • 3.2 定义表单类
          • 3.2.1 字段类型和验证器
          • 3.2.2 综合案例
        • 3.3 渲染表单
        • 3.4 处理表单提交
      • 4. 数据库操作和SQLAlchemy
        • 4.1 安装
        • 4.2 配置数据库连接
        • 4.3 定义数据模型类
        • 4.4 数据操作

1. Flask应用的基本组成部分

Flask应用的基本组成部分包括路由、视图函数、请求和响应。

1.1 路由(Routing)

路由(Routing)是将URL映射到相应的视图函数(View Function)上的过程。

在Flask中,可以通过装饰器来定义路由,如下所示:

from flask import Flaskapp = Flask(__name__) # 实例化一个Flask对象,最基本的写法@app.route('/')
def index():return 'Hello, World!'if __name__ == "__main__":app.run()

在Python中,装饰器(decorator)是一种特殊的函数,用于修改或增强其他函数的功能。装饰器是通过在被装饰函数的定义前加上@符号,将被装饰函数传递给装饰器函数作为参数来实现的。

在上面的代码中,我们通过app.route装饰器定义了一个路由,将/映射到index函数上。当用户在浏览器中访问/时,就会执行index函数,并返回'Hello, World!'这个字符串。

1.2 视图函数(View Function)

上面的例子中,index函数就是一个视图函数。

Flask应用中处理请求并返回响应的函数。视图函数通常会接收一些参数(如URL中的参数POST请求中的表单数据等),并根据这些参数进行处理,最后返回一个响应(如HTML页面、JSON数据等)。

1.3 请求(Request)

请求是Flask应用中接收客户端发来的数据的对象。

每次客户端发送一个HTTP请求时,Flask将会创建一个request对象。

在视图函数中,我们可以通过request对象获取客户端提交的数据(如表单数据、URL 参数等)。例如,下面的代码中,我们通过request.args.get方法获取了URL参数中的name参数:

from flask import Flask, requestapp = Flask(__name__)@app.route('/')
def index():name = request.args.get('name', 'World')return f'Hello, {name}!'

在浏览器中访问/?name=Flask,就会返回'Hello, Flask!'这个字符串。

下面是request一些常用的方法和属性:

  • request.method:HTTP请求方法,如 GET、POST、PUT、DELETE 等。
  • request.args:获取查询参数,返回一个不可变字典。
  • request.form:获取表单参数,返回一个不可变字典。
  • request.files:获取上传的文件,返回一个不可变字典。
  • request.headers:获取请求头,返回一个字典。
  • request.cookies:获取请求中的 cookies,返回一个字典。
  • request.remote_addr:获取客户端的 IP 地址。
  • request.path:获取请求路径,不包含查询参数。
  • request.url:获取完整的请求 URL。
  • request.is_xhr:判断请求是否是 AJAX 请求。
提取方法描述
request.cookies提取cookie字典信息
request.args.get(“name”)查询字符串参数 /user?name=curry&age=18
request.form.get(“name”)表单数据 {“name”: “james”, “age”: 38}
request.json.get(“name”)json格式字符串参数

参考连接:http://t.csdn.cn/kFwUR

1.4 响应(Response)

响应是Flask应用中返回给客户端的数据。

在视图函数中,我们可以通过return语句返回响应。

响应可以是各种格式的数据,如HTML页面、JSON数据、图片、文件等。例如,下面的代码中,我们返回了一个HTML页面:

from flask import Flaskapp = Flask(__name__)@app.route('/')
def index():return '

Hello, World!

'

在浏览器中访问 /,就会显示一个标题为'Hello, World!'的 HTML 页面。

在Flask中,我们可以使用make_response()函数来创建一个响应对象,并可以通过设置其内容、状态码、头部等属性来进行自定义。

例如,以下代码定义了一个包含自定义内容和状态码的响应:

from flask import Flask, make_responseapp = Flask(__name__)@app.route('/')
def hello_world():response = make_response('Hello World!', 200)# 这里设置了一个自定义的响应头,键为 'X-My-Header',值为 'my-value'response.headers['X-My-Header'] = 'my-value'return response

下面是response一些常用的方法和属性:

  • response.status_code:HTTP 响应状态码,如 200、404 等。
  • response.headers:HTTP 响应头,可以通过该属性设置自定义的响应头,返回一个字典。
  • response.content_type:HTTP 响应内容的 MIME 类型,如 text/html、application/json 等。
  • response.data:HTTP 响应内容,返回一个字节串。
  • response.set_cookie():设置 cookie。
  • response.delete_cookie():删除 cookie。
  • response.make_response():创建一个 Response 对象,可以通过该方法自定义响应内容和响应头。

官网地址:https://flask.palletsprojects.com/en/latest/

2. 模板引擎Jinja2的使用

Jinja2中文文档_w3cschool

Jinja2是Flask默认的模板引擎,它是一种基于Python语言的模板引擎,具有简单、高效、安全等特点。

Jinja2支持模板继承、变量替换、条件判断、循环遍历等常用的模板操作。

在Flask中,我们可以通过在应用程序中配置模板路径,然后在视图函数中使用render_template函数来渲染模板,将动态数据和静态内容结合起来,最终生成一个完整的HTML页面。

2.1 入门案例

来看一个例子,演示如何在Flask应用中使用Jinja2模板引擎:

# app.py
from flask import Flask, render_templateapp = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True   # 设置模板自动重载@app.route('/')
def index():return render_template('index.html', name='John Doe')

我们在Flask应用的根目录下创建一个templates文件夹,并在该文件夹下创建一个名为 index.html的模板文件。在该模板文件中,我们可以使用Jinja2提供的语法来渲染动态数据和静态内容。

image-20230226221318273

以下是一个简单的 index.html 模板文件的示例:


{<!-- -->{ name }} - My Flask App

Hello, {{ name }}!

  • {{ name }}:表示要渲染的动态数据,其中 name 是我们在视图函数中传递给模板的参数。

最后,我们可以通过访问 http://localhost:5000/ 来查看渲染后的页面效果,页面将会显示 Hello, John Doe!
Alt

注意:

  • app.config['TEMPLATES_AUTO_RELOAD'] = True 是 Flask 应用中配置模板自动重载的参数。如果将其设置为 True,则在修改模板文件后,Flask 会自动重载模板,从而使得修改后的模板能够生效。这在开发阶段非常有用,因为可以避免每次修改模板后都需要手动重启应用的麻烦。

csdn链接:http://t.csdn.cn/ENFfK

2.2 条件判断


{% if condition %}

条件为真

{% elif other_condition %}

其他条件为真

{% else %}

所有条件都为假

{% endif %}

2.3 循环遍历


{% for item in items %}
  • {{ item }}
  • {% else %}
  • 列表为空
  • {% endfor %}

    2.4 过滤器

    过滤器可以用管道符|链接到变量之后。

    例如,我们有一个变量name,我们可以使用capitalize过滤器将它的第一个字母大写:

    {{ name | capitalize }}
    

    还可以使用多个过滤器,其中每个过滤器的输出作为下一个过滤器的输入,如下所示:

    {{ name | lower | replace(" ", "_") }}
    

    上面把变量name中的所有字母都转换为小写,并将空格替换为下划线。

    Jinja2中的常见过滤器包括:

    • safe: 标记值为安全,将不进行转义
    • capitalize: 将字符串的第一个字符大写
    • lower: 将字符串转换为小写
    • upper: 将字符串转换为大写
    • title: 将字符串的每个单词的首字母大写
    • trim: 删除字符串开头和结尾的空白字符
    • replace: 将字符串中的某个子串替换为另一个字符串

    2.5 宏

    宏是 Jinja2 中可重用的代码块,可以在模板的任何地方调用。

    通过使用 Jinja2 中的 {% macro %} 标签定义宏,然后可以在模板的任何地方调用它。例如:

    {% macro hello(name) %}

    Hello, {{ name }}!

    {% endmacro %}

    这个宏定义了一个 hello 的宏,它接受一个名为 name 的参数,并返回一个带有 nameh1 标签。假设该宏在一个名为 hello_macro.html 的模板文件。

    接下来,我们在另一个模板文件中使用这个宏。内容如下:

    {% import 'hello_macro.html' as macros %}{{ macros.hello('World') }}
    

    这个文件中首先使用了 import 指令将 hello_macro.html 中的宏导入,并定义了一个名为 macros 的命名空间来包含这个宏。然后,我们就可以在文件中使用这个宏了。

    最终生成的 HTML 代码将是:

    Hello, World!

    如果是在同一文件调用:

    {{ hello('World') }}
    

    下面是一个相对复杂的例子:

    {% macro render_person(person) %}

    {{ person.name }}

    Age: {{ person.age }}

    {% if person.email %}

    Email: {{ person.email }}

    {% endif %}
    {% endmacro %}{% for person in people %}{{ render_person(person) }} {% endfor %}
    • 在上面的例子中,我们定义了一个名为 render_person 的宏,用于渲染一个人的信息。
    • 它接受一个 person 对象作为参数,并使用该对象的属性来渲染 HTML。
    • 在主模板中,我们使用 for 循环来遍历人的列表,并使用 render_person 宏来渲染每个人的信息。

    2.6 定义临时变量

    
    {% with title="Hello, World!" %}

    {{ title }}

    {% endwith %}{% with total = 1 + 2 %}{{ total }} {% endwith %}

    使用with定义的变量作用范围在{% with %}{% endwith %}之间。

    还可以使用set定义临时变量:

    {% set x = 1 %}
    {% if x %}{% set y = 2 %}
    {% endif %}{{ x }}  # 输出 1
    {{ y }}  # 报错,y未定义
    

    set 的作用范围是定义它的块级范围,块级范围内的变量名只在该块级范围内有效,出了这个范围,这个变量名就失效了。

    在这个例子中,{% set x = 1 %} 定义了变量 x,作用范围为整个模板。在 if 语句中,当 x 的值为真时,{% set y = 2 %} 定义了变量 y,作用范围为 if 语句块级范围。因此,当 if 语句的条件为假时,变量 y 未被定义,因此输出时会报错。

    宏和临时变量:

    • 宏是一段重复使用的代码块,它可以在模板中定义并在需要的地方调用。而临时变量则是在模板中定义的一个变量,它可以用来存储临时数据,并在模板中使用。
    • 宏和临时变量的区别在于它们的作用范围和生命周期不同。宏是一段代码块,它的作用范围只在它所定义的模板中,它的生命周期是整个应用程序的生命周期。而临时变量的作用范围只在当前的上下文中,它的生命周期只是当前请求处理过程中。

    2.7 定义模板

    在 Flask 中,可以通过定义基础模板扩展模板来实现代码的复用和管理,使得代码更加简洁和易于维护。

    定义基础模板可以使用 {% block %}{% endblock %} 标签,其中 {% block %} 定义了一个块,其内容可以被子模板继承和覆盖。

    在子模板中可以使用 {% extends %} 标签继承基础模板,同时通过 {% block %} 标签覆盖父模板中定义的块。

    举个例子,假设我们有一个父模板 base.html,它包含了一个名为 content 的块。现在我们想要创建一个子模板 child.html,它继承自父模板并重写 content 块,可以这样实现:

    
    
    {% block title %}{% endblock %}
    {% block content %}{% endblock %}
    
    {% extends "base.html" %}{% block title %}Child Template{% endblock %}{% block content %}

    Hello, World!

    {% endblock %}

    在子模板中:

    • 我们使用 {% extends "base.html" %} 声明了它继承自 base.html
    • 使用 {% block ... %} ... {% endblock %} 块声明了要重写的内容。
    • 这样,child.html 就拥有了 base.html 中的所有内容,并且可以根据自己的需求覆盖 base.html 中的块内容。
    • 当子模板被渲染时,Jinja2 会先加载父模板 base.html,然后替换其中的 content 块为子模板 child.html 中定义的内容。

    3. Flask-WTF表单处理和验证

    • 在 Flask 中,表单处理和验证一般使用 Flask-WTF 插件实现。
    • Flask-WTF 是 Flask 的一个扩展,它集成了 WTForms,是一个流行的 Python 表单处理库。使用 Flask-WTF 可以方便地创建表单,并对表单数据进行验证和处理。
    • 在 Flask-WTF 中,表单通常是通过定义一个继承自 FlaskForm 类的类来实现的。这个类中定义了表单中各个字段的类型、标签、验证规则等信息。
    • 使用 Flask-WTF 中的 form 对象可以在模板中生成表单,并通过 validate_on_submit() 方法对表单数据进行验证和处理。

    3.1 安装 Flask-WTF

    pip install Flask-WTF
    

    3.2 定义表单类

    在 Flask 中定义表单类可以使用 Flask-WTF 扩展中的 FlaskForm 类,也可以使用 WTForms 库中的 Form 类。后面主要以使用 FlaskForm 为例。

    每个表单字段都是一个实例变量,可以设置不同的参数,如字段类型、标签、验证规则等。

    例如,如果需要使用字符串类型字段和数据验证器,可以这样定义表单类:

    from flask_wtf import FlaskForm
    from wtforms import StringField, validatorsclass MyForm(FlaskForm):name = StringField('Name', validators=[validators.DataRequired()])
    

    在上面的代码中,定义了一个名为 MyForm 的表单类,其中包含一个字符串类型的 name 字段,该字段使用了 DataRequired 验证器,用于验证该字段的值是否为空。

    3.2.1 字段类型和验证器

    常用的字段类型:

    字段类型描述
    StringField字符串字段,用于接受字符串类型的数据
    IntegerField整型字段,用于接受整数类型的数据
    DecimalField十进制浮点型字段,用于接受浮点型数据,可以指定精度
    BooleanField布尔型字段,用于接受 True 或 False 类型的数据
    DateField日期型字段,用于接受日期类型的数据
    TimeField时间型字段,用于接受时间类型的数据
    DateTimeField日期时间型字段,用于接受日期时间类型的数据
    FileField文件上传字段,用于接受上传文件类型的数据
    RadioField单选按钮字段
    CheckboxField复选框字段

    验证器:

    DataRequired确保字段不为空message
    EqualTo比较两个字段的值是否相等message, fieldname
    Length确保字段值的长度在给定范围内message, min, max
    Email确保字段值是合法的电子邮件地址message
    URL确保字段值是合法的 URL 地址message
    NumberRange确保字段值在数字范围内message, min, max
    Regexp使用正则表达式验证字段值message, regex
    Optional使字段变为可选项

    参数message表示自定义错误提示信息。如果参数未指定,则使用默认的错误提示信息。

    3.2.2 综合案例
    from flask_wtf import FlaskForm
    from wtforms import StringField, PasswordField, SubmitField
    from wtforms.validators import DataRequired, Length, Email, EqualToclass RegistrationForm(FlaskForm):"""注册表单类"""username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])email = StringField('Email', validators=[DataRequired(), Email()])password = PasswordField('Password', validators=[DataRequired()])confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])submit = SubmitField('Sign Up')
    

    这个表单类定义了一个用户注册表单,包含用户名、电子邮件、密码和确认密码等字段。

    其中,StringField表示字符串类型的字段,PasswordField表示密码类型的字段,SubmitField表示提交按钮类型的字段。

    验证器中,DataRequired表示该字段必须填写,Length表示该字段长度限制,Email表示该字段必须是电子邮件格式,EqualTo表示该字段必须与另一个字段相等。

    最后,submit表示提交按钮。

    3.3 渲染表单

    视图函数中,可以通过创建一个表单对象来渲染表单,并将其传递给模板进行渲染。

    在模板中,可以使用 form. 来渲染表单字段。

    下面是一个简单的视图函数的示例:

    from flask import render_template
    from app import app
    from forms import LoginForm@app.route('/login')
    def login():form = LoginForm()return render_template('login.html', form=form)
    

    3.4 处理表单提交

    处理表单提交时的一般流程如下:

    1. 用户在浏览器端填写表单并点击“提交”按钮,浏览器向服务器发送POST请求;
    2. Flask应用接收到请求,解析请求体中的表单数据,生成一个request对象;
    3. Flask应用根据请求的URL和请求方法选择对应的视图函数进行处理;
    4. 视图函数从request对象中获取表单数据,对数据进行验证和处理;
    5. 如果表单数据验证通过,视图函数进行相应的业务逻辑处理;
    6. 如果表单数据验证不通过,视图函数返回一个带有错误信息的响应,通常是重新渲染表单页面,并在页面中显示相应的错误信息;
    7. 视图函数根据业务逻辑的处理结果,生成响应对象,并返回给客户端。

    4. 数据库操作和SQLAlchemy

    在Flask中,常用的数据库操作有两种方式:

    1. 使用原生的SQL语句操作数据库。
    2. 使用ORM框架操作数据库,常用的ORM框架有SQLAlchemy。

    下面我们主要介绍使用SQLAlchemy的方式。

    SQLAlchemy是Python中最著名的ORM框架之一,它提供了高度封装的SQL操作方式,可以让我们使用Python语言来操作数据库,而不用编写复杂的SQL语句。

    SQLAlchemy还提供了非常好的数据模型定义方式,可以大大减少我们编写数据库代码的工作量。

    4.1 安装

    pip install SQLAlchemy
    

    4.2 配置数据库连接

    安装完成后,我们需要在Flask应用中配置数据库连接,以便于在应用中使用。Flask中的数据库连接配置通常保存在app.config对象中。

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://username:password@hostname/database_name'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    db = SQLAlchemy(app)
    

    上面的代码中,我们定义了一个Flask应用,并使用SQLAlchemy连接到了一个MySQL数据库。

    其中,'username’和’password’分别是数据库用户名和密码,'hostname’是数据库服务器地址,'database_name’是数据库名。

    4.3 定义数据模型类

    在Flask应用中,我们需要定义数据模型类,以便于ORM框架进行数据操作。

    下面是一个简单的数据模型类的定义:

    from datetime import datetime
    from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()class User(db.Model):__tablename__ = 'users'id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(50), nullable=False)email = db.Column(db.String(120), unique=True, nullable=False)password = db.Column(db.String(60), nullable=False)created_at = db.Column(db.DateTime, default=datetime.utcnow)def __repr__(self):return ''.format(self.name)
    

    上面的代码中,我们定义了一个User数据模型类,它继承自db.Model类,这个类是SQLAlchemy提供的基类,用来定义数据模型类。

    在User类中,我们定义了表名、字段名和字段类型等信息,这些信息会被SQLAlchemy自动映射到数据库中。

    在__repr__方法中,我们定义了打印对象时的输出信息。

    4.4 数据操作

    定义好数据模型类之后,我们就可以使用ORM框架进行数据操作了。

    ORM框架提供了各种各样的查询方法,例如查询所有数据、查询单个数据、过滤数据等。

    下面是一些简单的查询方法的例子:

    # 查询所有用户
    users = User.query.all()# 查询第一个用户
    user = User.query.first()# 根据id查询用户
    user = User.query.get(1)# 过滤数据
    users = User.query.filter_by(name='Alice').
    

    相关内容

    热门资讯

    iOSapp移植到安卓系统,i... 你有没有想过,那些在iOS上让你爱不释手的app,是不是也能在安卓系统上大放异彩呢?今天,就让我带你...
    现在安卓随便换系统,探索个性化... 你知道吗?现在安卓手机换系统简直就像换衣服一样简单!没错,就是那种随时随地、随心所欲的感觉。今天,就...
    安卓系统安装按钮灰色,探究原因... 最近发现了一个让人头疼的小问题,那就是安卓手机的安装按钮突然变成了灰色,这可真是让人摸不着头脑。你知...
    安卓7.1.1操作系统,系统特... 你知道吗?最近我在手机上发现了一个超级酷的新玩意儿——安卓7.1.1操作系统!这可不是什么小打小闹的...
    安卓os系统怎么设置,并使用`... 你有没有发现,你的安卓手机有时候就像一个不听话的小孩子,有时候设置起来真是让人头疼呢?别急,今天就来...
    安卓降低系统版本5.1,探索安... 你知道吗?最近安卓系统又来了一次大动作,竟然把系统版本给降到了5.1!这可真是让人有点摸不着头脑,不...
    解放安卓系统被保护,解放安卓系... 你有没有想过,你的安卓手机其实可以更加自由地呼吸呢?是的,你没听错,我说的就是解放安卓系统被保护的束...
    校务帮安卓系统下载,便捷校园生... 你有没有想过,你的手机里装了一个神奇的助手——校务帮安卓系统下载?没错,就是那个能让你轻松管理学校事...
    安卓系统没有拼多多,拼多多崛起... 你知道吗?最近我在手机上发现了一个小小的秘密,那就是安卓系统里竟然没有拼多多这个应用!这可真是让我大...
    甜城麻将安卓系统,解锁全新麻将... 你有没有听说过那个超级火的甜城麻将安卓系统?没错,就是那个让无数麻将爱好者为之疯狂的软件!今天,就让...
    安卓系统卸载的软件,深度揭秘卸... 手机里的软件越来越多,是不是感觉内存不够用了?别急,今天就来教你怎么在安卓系统里卸载那些不再需要的软...
    安卓系统推荐好游戏,畅享指尖乐... 手机里的游戏可是咱们休闲娱乐的好伙伴,尤其是安卓系统的用户,选择面那可是相当广呢!今天,就让我来给你...
    王者安卓系统怎么卖,揭秘如何轻... 你有没有听说最近王者安卓系统的火爆程度?没错,就是那个让无数玩家沉迷其中的王者荣耀!今天,我就来给你...
    安卓开发系统内置证书,基于安卓... 你有没有想过,你的安卓手机里那些神秘的内置证书,它们到底是个啥玩意儿?别急,今天就来给你揭秘这些隐藏...
    荣耀安装安卓原生系统,深度体验... 你知道吗?最近荣耀手机界可是掀起了一股热潮,那就是——荣耀安装安卓原生系统!这可不是什么小打小闹,而...
    安卓13小米系统,创新功能与流... 你知道吗?最近安卓13系统可谓是风头无两,各大手机厂商纷纷推出自家的新版系统,其中小米的安卓13系统...
    鸿蒙系统底层安卓10,融合与创... 你知道吗?最近手机圈里可是热闹非凡呢!华为的新操作系统鸿蒙系统,竟然在底层采用了安卓10的架构。这可...
    安卓系统辅助在哪关闭,轻松关闭... 你有没有发现,安卓系统的辅助功能真是贴心到不行啊!不过,有时候这些功能太多,用起来有点乱糟糟的。别急...
    安卓系统outlook邮件设置... 你有没有发现,自从你把手机升级到了安卓系统,邮件管理变得有点复杂呢?别急,今天就来手把手教你如何设置...
    安卓系统停止向华为,自主操作系... 你知道吗?最近科技圈可是炸开了锅!安卓系统突然宣布停止向华为提供技术支持,这可不仅仅是两家公司之间的...