当前位置:   article > 正文

【Web开发】Flask框架基础知识_flask前端框架选择

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的用户数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/185711?site
推荐阅读
相关标签
  

闽ICP备14008679号