【Web开发】Flask框架基础知识

举报
zstar 发表于 2022/08/06 00:01:34 2022/08/06
【摘要】 本篇主要是黑马程序员的Flask快速入门教程的笔记 Flask简介 Flask诞生于2010年,是用Python语言基于Werkzeug工具箱编写的轻量级Web开发框架。 Flask的常用...

本篇主要是黑马程序员的Flask快速入门教程的笔记

Flask简介

Flask诞生于2010年,是用Python语言基于Werkzeug工具箱编写的轻量级Web开发框架。

Flask的常用扩展包:

  • Flask-SQLalchemy:操作数据库;
  • Flask-migrate:管理迁移数据库;
  • Flask-Mail:邮件;
  • Flask-WTF:表单;
  • Flask-Bable:提供国际化和本地化支持,翻译;
  • Flask-script:插入脚本;
  • Flask-Login:认证用户状态;
  • Flask-OpenID:认证;
  • Flask-RESTful:开发REST API的工具;
  • Flask-Bootstrap:集成前端Twitter Bootstrap框架;
  • Flask-Moment:本地化日期和时间;
  • Flask-Admin:简单而可扩展的管理接口的框架

相关文档:
中文文档:http://docs.jinkan.org/docs/flask/
英文文档:http://flask.pocoo.org/docs/0.12/

Flask安装

pip install flask

  
 
  • 1

我安装的版本是Flask 2.1.3

拓展命令:
将当前环境打包成requirements.txt

pip freeze >requirements.txt

  
 
  • 1

将需要的环境一起安装:

pip install -r requirements.txt

  
 
  • 1

基本框架

在Pycharm中,可以直接新建一个Flask模板文件,运行后,可以在浏览器在中输出Hello World。

在这里插入图片描述

相关注释如下:

from flask import Flask

# 指向程序所在的模块
app = Flask(__name__)


# 将路由映射到视图函数index
@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    # 启动WEB服务器
    app.run()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

路由请求方式限定

默认情况下,路由仅支持Get请求方式,可用下

@app.route('/', methods=['GET', 'POST'])
def hello_world():
    return 'Hello World!'

  
 
  • 1
  • 2
  • 3

路由传递参数

在路由中使用<>可以传递参数,使用int可以限定整形数据

@app.route('/orders/<int:order_id>')
def order(order_id):
    print(type(order_id))  # 类型为int
    return 'this is order %d' % order_id

  
 
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

Jinja2模板引擎

Jinja2:是Python下一个被广泛应用的模板引擎,是Flask内置的模板语言。

简单使用

Jinja2提供了render_template函数,来渲染html文件。
下面简单来使用一下:

先导入render_template

from flask import Flask, render_template

  
 
  • 1

在templates文件夹下新建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
测试Jinja2
</body>
</html>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

进行调用

@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template('index.html')

  
 
  • 1
  • 2
  • 3

注释

使用 {# #} 进行可以进行注释

变量/控制语句

在路由函数里,可以自定义变量,然后在render_template函数中进行参数传递,例如:

@app.route('/', methods=['GET', 'POST'])
def index():
    my_list = [1, 2, 3, 4, 5]
    return render_template('index.html', num_list=my_list)

  
 
  • 1
  • 2
  • 3
  • 4

num_list对应html文件中的变量。

在html中循环输出:
index.html:

<body>
{% for num in num_list %}
    {{ num }}
{% endfor %}
</body>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

小技巧:先写for,再按Tab可使用代码补全

输出效果:
在这里插入图片描述

过滤器

过滤器即Flask提供的一些函数,可以直接进行调用简化操作。

例如:使用lower可以实现字符串转小写, 使用length可以获取列表长度。
输入:

<body>
{#字符串转小写#}
<p>{{ 'HELLO' | lower }}</p>
{#获取列表长度#}
<p>{{ [1,2,3,4,5,6] | length }}</p>
</body>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

输出:
在这里插入图片描述
注:使用连续的|可以同时使用多个过滤器

更多过滤器总结:

字符串操作

  • safe:禁用转义
<p>{{ '<em>hello</em>' | safe }}</p>

  
 
  • 1
  • capitalize:把变量值的首字母转成大写,其余字母转小写
<p>{{ 'hello' | capitalize }}</p>

  
 
  • 1
  • lower:把值转成小写
<p>{{ 'HELLO' | lower }}</p>

  
 
  • 1
  • upper:把值转成大写
<p>{{ 'hello' | upper }}</p>

  
 
  • 1
  • title:把值中的每个单词的首字母都转成大写
<p>{{ 'hello' | title }}</p>

  
 
  • 1
  • reverse:字符串反转
<p>{{ 'olleh' | reverse }}</p>

  
 
  • 1
  • format:格式化输出
<p>{{ '%s is %d' | format('name',17) }}</p>

  
 
  • 1
  • striptags:渲染之前把值中所有的HTML标签都删掉
<p>{{ '<em>hello</em>' | striptags }}</p>

  
 
  • 1
  • truncate: 字符串截断
<p>{{ 'hello every one' | truncate(9)}}</p>

  
 
  • 1

列表操作

  • first:取第一个元素
<p>{{ [1,2,3,4,5,6] | first }}</p>

  
 
  • 1
  • last:取最后一个元素
<p>{{ [1,2,3,4,5,6] | last }}</p>

  
 
  • 1
  • length:获取列表长度
<p>{{ [1,2,3,4,5,6] | length }}</p>

  
 
  • 1
  • sum:列表求和
<p>{{ [1,2,3,4,5,6] | sum }}</p>

  
 
  • 1
  • sort:列表排序
<p>{{ [6,2,3,1,5,4] | sort }}</p>

  
 
  • 1

语句块过滤

{% filter upper %}
    一大堆文字
{% endfilter %}

  
 
  • 1
  • 2
  • 3

Flask-WTF表单

在Flask中,为了处理web表单,我们一般使用Flask-WTF扩展,它封装了WTForms,并且它有验证表单数据的功能

以最常见的登录验证为例,这里以普通实现方式和WTF表单方式实现进行比较。

普通方式

html

<form method="post">
    <label>用户名:</label><input type="text" name="username"><br>
    <label>密码:</label><input type="password" name="password"><br>
    <label>确认密码:</label><input type="password" name="password2"><br>
    <input type="submit" value="提交"><br>
    {% for message in get_flashed_messages() %}
        {{ message }}
    {% endfor %}
</form>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

app.py

from flask import Flask, render_template, request, flash

# 指向程序所在的模块
app = Flask(__name__)

# Flask-WTF需要配置参数SECRET_KEY
app.secret_key = 'zstar'


@app.route('/', methods=['GET', 'POST'])
def hello_world():
    # 1. 判断请求方式是post
    if request.method == 'POST':
        # 2. 获取参数, 并效验参数完整性, 如果有问题就进行flash
        username = request.form.get('username')
        password = request.form.get('password')
        password2 = request.form.get('password2')
        if not all([username, password, password2]):
            flash('params error')

        # 3. 效验密码
        elif password != password2:
            flash('password error')

        # 4. 没有问题就返回'success'
        else:
            print(username)
            return 'success'

    return render_template('index.html')


if __name__ == '__main__':
    # 启动WEB服务器
    app.run()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

代码说明:
后端使用request.form.get的来获取前端表单数据
验证主要来验证两次登录输入密码是否一致
提示信息使用flash来进行映射,前端使用get_flashed_messages来获取映射的信息。

WTF表单方式

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post">
    {#设置csrf_token(python3版本不需要)#}
    {{ form.csrf_token() }}
    {{ form.username.label }}{{ form.username }}<br>
    {{ form.password.label }}{{ form.password }}<br>
    {{ form.password2.label }}{{ form.password2 }}<br>
    {{ form.input }}<br>
    {% for message in get_flashed_messages() %}
        {{ message }}
    {% endfor %}
</form>
</body>
</html>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

app.py

from imp import reload
from flask import Flask, render_template, request, flash
# 导入wtf扩展的表单类
from flask_wtf import FlaskForm

# 导入自定义表单需要的字段
from wtforms import SubmitField, StringField, PasswordField

# 导入wtf扩展提供的表单验证器
from wtforms.validators import DataRequired, EqualTo

# # 解决编码问题
# import sys
# reload(sys)

app = Flask(__name__)
app.config['SECRET_KEY'] = 'zstar'


# 自定义表单类,文本字段、密码字段、提交按钮
# 需要自定义一个表单类
class RegisterForm(FlaskForm):
    username = StringField('用户名:', validators=[DataRequired()])
    password = PasswordField('密码:', validators=[DataRequired()])
    password2 = PasswordField('确认密码:', validators=[DataRequired(), EqualTo('password', '密码输入不一致')])
    input = SubmitField('提交')


# 定义根路由视图函数,生成表单对象,获取表单数据,进行表单数据验证
@app.route('/form', methods=['GET', 'POST'])
def form():
    register_form = RegisterForm()

    if request.method == 'POST':
        # 调用validate_on_submit方法, 可以一次性执行完所有的验证函数的逻辑
        if register_form.validate_on_submit():
            # 进入这里就表示所有的逻辑都验证成功
            username = request.form.get('username')
            password = request.form.get('password')
            password2 = request.form.get('password2')
            print(username)
            return 'success'
        else:
            flash('参数有误')

    return render_template('index.html', form=register_form)


if __name__ == '__main__':
    # 启动WEB服务器
    app.run()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

代码说明:
使用WTF表单方式的好处是对于密码一致性的不再需要单独进行验证,而是在后端直接将表单封装了成了一个类。
其中,StringField指定了表单提交的数据类型为String,DataRequired表明该项为必填项,EqualTo封装了两个表单的一致性比较过程,最后调用register_form.validate_on_submit来一次性提交所有的验证逻辑。
前端方面,通过form可以直接对接到后端定义的表单属性,其中python2需要添加 {{ form.csrf_token() }}来指定表单的token,在python3版本中,实测不需要该语句也能运行。

WTForms支持的HTML标准字段有下面这些:

字段对象 说明
StringField 文本字段
TextAreaField 多行文本字段
PasswordField 密码文本字段
HiddenField 隐藏文件字段
DateField 文本字段,值为datetime.date文本格式
DateTimeField 文本字段,值为datetime.datetime文本格式
IntegerField 文本字段,值为整数
DecimalField 文本字段,值为decimal.Decimal
FloatField 文本字段,值为浮点数
BooleanField 复选框,值为True和False
RadioField —组单选框
SelectField 下拉列表
SelectMutipleField 下拉列表,可选择多个值
FileField 文件上传字段
submitField 表单提交按钮
FormField 把表单作为字段嵌入另—个表单
FieldList —组指定类型的字段

WTForms常用验证函数:

验证函数 说明
DataRequired 确保字段中有数据
EqualTo 比较两个字段的值,常用于比较两次密码输入
Length 验证输入的字符串长度
NumberRange 验证输入的值在数字范围内
URL 验证URL
AnyOf 验证输入值在可选列表中
NoneOf 验证输入值不在可选列表中

数据库

在flask中,可以利用SQLAlchemy来进行数据库的操作。

SQLAlchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了SQLAlchemy操作的flask扩展。

flask-sqlalchemy安装

pip install flask-sqlalchemy
pip install mysqlclient

  
 
  • 1
  • 2

直接安装mysqlclient可能会安装失败,我去官网下了轮子:
mysqlclient-1.4.6-cp37-cp37m-win_amd64:https://pan.baidu.com/s/1TiLRPUWjQc8HS7ELlGcxHw?pwd=8888

安装mysql

安装mysql可以参阅这篇博文:Windows10安装MySQL傻瓜式教程(图文教程)

使用下面的命令可以启动/停止mysql服务

# 停止mysql服务
net stop mysql57 
# 启动mysql服务
net start mysql57

  
 
  • 1
  • 2
  • 3
  • 4

安装好之后,可以通过Navicat连接本地数据库进行可视化:

在这里插入图片描述

使用示例

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)


class Config(object):
    """配置参数"""
    # sqlalchemy的配置参数
    SQLALCHEMY_DATABASE_URI = "mysql://root:你的密码@127.0.0.1:3306/zstar"

    # 设置sqlalchemy自动更跟踪数据库
    SQLALCHEMY_TRACK_MODIFICATIONS = True

    # 查询时会显示原始SQL语句
    app.config['SQLALCHEMY_ECHO'] = True


# 连接数据库
app.config.from_object(Config)

# 创建数据库aqlalchemy工具对象
db = SQLAlchemy(app)


class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), unique=True)
    user = db.relationship('User', backref='role')


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), unique=True, index=True)
    email = db.Column(db.String(32), unique=True)
    password = db.Column(db.String(32))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))


@app.route("/")
    # 第一种查询方式
    from sqlalchemy import text
    sql = text("select * from roles")
    result = db.engine.execute(sql)
    for row in result:
        print(row)
    # 第二种查询方式
    # print(Role.query.all())
    # print(Role.query.filter_by(id=2).first())

@app.route("/create")
def create():
    role1 = Role(name="admin")
    # session记录对象任务
    db.session.add(role1)
    # 提交任务到数据库中
    db.session.commit()
    return "The Role is created"

# 创建表:
# db.create_all()

# 删除表
# db.drop_all()


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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

本例中,首先需要手动创建数据库zstar,然后配置数据库连接ip和账号密码mysql://root:你的密码@127.0.0.1:3306/zstar,之后使用db.create_all()会创建前面定义出的数据表,同理db.drop_all()会删除前面定义出的数据表。这两句实测必须放在if __name__ == '__main__':外面,否则不会被运行,未知具体原因。

本例中,我定义了两个接口,第一个根目录接口,分别尝试了通过sql来从直接查询和调用对象进行查询的两种查询方式,第二个/create接口,实现了向数据表Role中插入一个名称为admin的用户数据。

文章来源: zstar.blog.csdn.net,作者:zstar-_,版权归原作者所有,如需转载,请联系作者。

原文链接:zstar.blog.csdn.net/article/details/126015400

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。