文章目录

Flask_脚本

1 集成Python shell

在我们实际的开发中,不免有一些任务需要在shell下完成。比如为cms后台添加超级管理员的需求,又比如迁移数据库的需求,定时任务等等,诸如这类需求更适合在shell中去操作(大部分需要在shell中去操作的都是权限比较高的任务)。

提示:迁移数据库就是用来解决数据库更新问题,解决之前我们学的db.create_all()db.drop_all()更新数据库的时候丢失数据的问题。
flask官方提供了一个扩展组件flask-script可以实现在shell下操作我们的Flask项目。

1.1 flask-script的用法:

1 由于flask-script是Flask的一个扩展组件,同往常一样首先在虚拟环境中安装我们的flask_script包。

pip install flask-script

1.1.1 实例:flask-script的简单实现

提示:实例下面有讲解
项目目录

│  manage.py
│ server.py

├─static # 文件夹
├─templates # 文件夹

server.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello World!' if __name__ == '__main__':
app.run()

manage.py

from flask_script import Manager
from server import app manager = Manager(app) @manager.command
def hello():
print('hello world') if __name__ == '__main__':
manager.run()

解读:manage.py
(1)flask_script模块中导入flask_script的核心类Manager

from flask_script import Manager

(2)server.py模块中把app对象导入

from server import app

(3)Manager()类传入app对象实例化出manager对象,manager对象用于以后所有添加命令相关操作

manager = Manager(app)

(4) 利用@manager.command装饰器添加以被装饰函数的名字命名的一条命令被装饰函数的映射

@manager.command   # 相当于添加了一条hello命令,可以调用到hello函数
def hello():
print('hello world')

(5) manager需要调用run方法,之前定义的命令才会生效

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

shell下操作命令
shell中切入到该manage.py的目录下,并且进入虚拟环境。输入命令python manage.py hello

>>python manage.py hello

命令中的hello@manager.command装饰器装饰的函数名
执行命令后会调用hello函数
如图所示实现了调用hello函数

1.1.1命令添加方式:

第一种(无参命令):

使用manager.commad方式添加命令:

...
@manager.command
def demo():
print('无参命令')
...

切入到manage.py所在的目录中,切入到虚拟环境,执行如下命令

>> python manage.py demo

第二种(有参命令):

使用manager.option('-简写的命令',‘--全写的命令’,dest=‘传给函数的形参’)添加命令:

...
@manager.option("-u","--username",dest="username")
@manager.option("-p","--password",dest="password")
def login(username, password):
print("用户名:{} 密码: {}".format(username,password))
...

切入到manage.py所在的目录中,切入到虚拟环境,执行如下命令.

>>python manage.py login -u mark -p 123

第三种(子命令):

比如一个功能对应着很多个命令,这个时候就可以用子命令来实现,可以将这些命令的映射单独放到一个文件方便管理。在这个放着很多命令映射的文件中实例化Manager类出一个新的对象,并在manage.py文件中通过manager.add_command("子命令",Manager对象)来添加子命令

实例:
在之前的1.1.1实例的项目目录中新建文件db_script.py

│  manage.py
│ server.py
│ db_script.py

├─static # 文件夹
├─templates # 文件夹

db_script.py

from flask_script import Manager

db_Manager = Manager()

@db_Manager.command
def init():
print('初始迁移仓库') @db_Manager.command
def migrate():
print('生成迁移脚本') @db_Manager.command
def upgrade():
print("迁移脚本映射到数据库")

manage.py

from flask_script import Manager
from server import app
from db_script import db_Manager # 导入子命令文件的Manager类实例化出的对象
manager = Manager(app) manager.add_command("db",db_Manager) # 添加子命令 ...

切入到manage.py所在的目录中,切入到虚拟环境,执行如下命令.

python manage.py db init
python manage.py db migrate
python manage.py db upgrade

2 项目重构

2.1 解耦配置信息以及模型文件信息触发循环导入问题

随着项目代码的增多 我们再把连接数据库的信息放到主app文件当中会应影响我们代码的可读性,那么我们相关数据库配置的信息应该放到一个config文件当中去,像我们当时加载debug配置一样使用app.config.from_object(config)一样加载我们的数据库连接信息。 新建config.py文件,把连接数据库相关的信息放到config.py中去,然后在主app文件中加载配置信息app.config.from_object(config)

config.py

HOST = '127.0.0.1'
PORT = '3306'
DATABASE_NAME = '01_db'
USERNAME = 'root'
PASSWORD = 'root' DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{databasename}?charset=utf8mb4"\
.format(username=USERNAME,password=PASSWORD,host=HOST,port=PORT,databasename=DATABASE_NAME) SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False

那么主app中的模型的文件也十分影响代码易读性,也应该新开一个modles文件夹,把我们的模型表放到modles中去
models.py

from app import db

class UserInfo(db.Model):
id = db.Column(db.Integer,primary_key=True,autoincrement=True,nullable=False)
name = db.Column(db.String(30),server_default='',comment="姓名")
tel = db.Column(db.String(16),server_default='',comment="电话"

app.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config
from models import UserInfo app = Flask(__name__)
app.config.from_object(config) db = SQLAlchemy(app) @app.route('/')
def hello_world():
return 'Hello World!' if __name__ == '__main__':
app.run()

这是代码易读性提高了,但是新的问题随之出现了,出现了一个循环导入的问题。
app.py 文件导入了models,我们python中而导入文件必然会把需要导入的文件从上到下执行一遍,那么就触发了models的执行,而models执行的时候需要从app导入db,出现了一个死循环如下图,这就是python循环导入的问题。

2.2 重构项目解决循环导入问题

为了解耦配置信息以及模型表信息,导致了models.pyapp.py出现了循环导入问题,我们的解决方案是新开启一个文件exts.py,在exts.py中生成db对象,解决循环导入问题。

实例2.2.1:解决循环导入问题之后重构项目
项目目录:

│  app.py
│ config.py
│ exts.py
│ models.py

├─static # 文件夹
├─templates # 文件夹

config.py

HOST = '127.0.0.1'
PORT = '3306'
DATABASE_NAME = '01_db'
USERNAME = 'root'
PASSWORD = 'root' DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{databasename}?charset=utf8mb4"\
.format(username=USERNAME,password=PASSWORD,host=HOST,port=PORT,databasename=DATABASE_NAME) SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False

exts.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

models.py

from exts import db

class UserInfo(db.Model):
__tablename__ = 'user_info'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(20),nullable=False,server_default='')

app.py

from flask import Flask
from exts import db
import config
from models import UserInfo app = Flask(__name__)
app.config.from_object(config) db.init_app(app) @app.route('/')
def hello_world():
return 'Hello World!' if __name__ == '__main__':
app.run()

3 使用Flask-Migrate迁移数据库

之前我们更新数据库的方式是先删除表然后再创建表简单粗暴,但是会丢失掉所有原来表中的数据。做web开发的我们应该深知数据无价,所以这个时候需要数据库迁移工具来完成这个工作,SQLAlcheme的开发者Michael Bayer开发了一个数据库迁移工具—Alembic来实现数据库的迁移,SQLAlchemy翻译成汉语是炼金术,而蒸馏器(Alembic)正是炼金术士最需要的工具。
我们的flask-sqlalchmy扩展组件正是基于SQLAlchemy,当然Flask也有专门做数据库迁移的扩展组件Flask-Migrate,同样Flask-Migrate正是基于Alembic

3.1 Flask-Migrate的用法:

1 由于flask-migrate是Flask的一个扩展组件,同往常一样首先在虚拟环境中安装我们的flask_migrate包。

pip install flask-migrate

为了导出数据库迁移命令,Flask-Migrate提供了一个MigrateCommand类,可附加到Flask-Script的manager对象上。在这个例子中,MigrateCommand类使用db命令附加。
我们的Flask_Migrate的操作是在shell下完成的,所以要基于Flask-scriptFlask-Migrate提供了一个MigrateCommand类,需要附加到Flask-Scriptmanager对象上,完成命令的创建,并且Flask_Migrate同时体统了Migrate类,需要加载核心对象app和数据库对象db。完成迁移工具的配置。

实例3.1.1:配置Flask_Migrate

首先在实例2.2.1中创建manage.py
manage.py代码如下

from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from exts import db
from server import app
manager = Manager(app) Migrate(app,db) manager.add_command('db',MigrateCommand)

解读:
(1) 首先从flask_migrate中导入 Migrate,MigrateCommand

from flask_migrate import Migrate,MigrateCommand

(2)Migrate加载app对象和db对象获取数据库的配置信息以及模型表信息。

Migrate(app, db)

(3)MigrateCommand附加到manager创建迁移数据库的子命令

manager.add_command('db',MigrateCommand)

迁移脚本命令

(1)创建迁移仓库
首先切换到项目目录下并且切入到虚拟环境中输入命令python manage.py db init

>> python manage.py db init

该命令初始化我们的迁移仓库,并且在我们的项目目录中创建迁移仓库文件

(2) 创建迁移脚本
依然在我们的shell中输入命令python manage.py db migrate

>> python manage.py db migrate

该命令会在数据库创建一张 alembic_version 表,存放着数据库迁移脚本的版本信息,该命令会搜集到需要迁移的模型表信息,写入到脚本中,但是并没有真正的映射到数据库中。
(3)更新数据库
依然在我们的shell中输入命令python manage.py db upgrade

python manage.py db upgrade

对于第一次迁移来说,其作用和db.create_all()方法一样,但是在随后的迁移中,upgrade命令可以把模型表改动的部分映射到数据库中,实现了一个更新的效果,并且不影响之前保存的数据。
提示:在首次执行这个命令之前如果该数据库的库内已经有了一些表,并且这些表没有与我们的模型映射,会自动删除掉这些表。

2 flask知识点补充

01-cookie

1.1 什么是cookie?

cookie技术产生源于HTTP协议在互联网上的急速发展,在浏览器发展初期,为了适应用户的需求,技术上推出了各种保持web浏览状态的手段,为什么要保持web浏览器的状态呢?
一般web通信是基于HTTP的,HTTP是无状态的协议,也就是说,在一次请求响应结束后,服务器不会留下任何有关于对方状态信息,所以需要保持web浏览器的状态。
比如:对于有些web应用来说,客户端的某些信息必须被记住。比如用户登录过后跳转页面依然要保持登录的状态,进行其他的业务访问,而当这个登录过的用户再次访问web服务器的时候,web服务器并不知道这个用户已经登录过了,所以无法进行其他需要权限的业务访问。所以cookie技术的出现就是为了解决这个问题。
cookie的具体实现过程:当一个用户访问web服务器后,web服务器会获取用户的状态并且返回一些数据(cookie)给浏览器,浏览器会自动储存这些数据(cookie),当用户再次访问web服务器,浏览器会把cookie放到请求报文中发送给web服务器,web服务器就会获取到了用户的状态。基于这次用户的状态方便用户进行其他业务的访问,并且web服务器可以设置浏览器保存cookie的时间,cookie是有域名的概念,只有访问同一个域名的时候才会把之前相同域名返回的cookie携带给该web服务器。
附注:1993年,网景公司雇员Lou Montulli为了提升用户体验,进一步实现了个人化网络。发明了今天广泛使用的Cookie

关键词

  • web通讯一般基于HTTP协议,HTTP是无状态协议。
  • Cookie技术是用来保持web访问状态,Cookie技术通过在请求和响应报文中添加Cookie数据来保存客户端的状态信息
  • 服务器可以设置cookie的有效期,浏览器会自动清除过期的cookie
  • cookie有域名的概念,只有访问同一个域名,才会把之前相同域名返回的cookie携带给该服务器。

1.2 如何在flask中使用cookie?

1.2.1 设置cookie

设置cookie的时候是由我们web服务器设置,也就是在Flask项目中生成cookie,经由响应报文返回给浏览器保存cookie,下次浏览器再访问web服务器的时会在请求报文中把cookie携带过来,所以cookie产生的起点是在web服务器中,也就是我们的Flask项目中。
在Flask中如果想要在响应中添加一个cookie,最方便的做法是使用内置的Response类提供的set_cookie()方法。

表-2.2.1.1 set_cookie()方法的参数

属性 说明
key cookie的键(名称)
value cookie的值
max_age cookie被保存的时间数,单位为秒。
expires 具体的过期时间,一个datetime对象或UNIX时间戳
path 限制cookie只在给定的路径可用,默认为整个域名下路径都可用
domain 设置cookie可用的域名,默认是当前域名,子域名需要利用通配符domain=.当前域名
secure 如果设为True,只有通过HTTPS才可以用
httponly 如果设为True,进制客户端JavaScript获取cookie
1.2.1.2 实例:设置cookie

项目目录

│  app.py

├─static # 文件夹
└─templates # 文件夹

app.py

from flask import Flask, Response

app = Flask(__name__)

@app.route('/')
def hello_world():
resp = Response('设置cookie给浏览器')
resp.set_cookie('user_name', 'mark') return resp if __name__ == '__main__':
app.run()

解读 app.py
(1) 首先导入Flask内置的Response类,用于在响应报文中设置cookie

from flask import Flask,request, Response

(2) 在视图函数实例化Response类并传入返回的内容,Response类实例化出的对象调用set_cookie()方 法,set_cookie内的第一个参数是设置cookie的key,第二个参数是用来设置cookie的value,然后返回该对象,就会携带着设置好的cookie返回给浏览器保存。

@app.route('/')
def hello_world():
resp = Response('设置cookie给浏览器')
resp.set_cookie('user_name', 'mark') return resp
1.2.1.3 在浏览器中查看cookie的三种方式(以Chrome浏览器为例)

基于2.2.1.2实例
第一种: 右键检查----->Network---->找到访问的域名---->找到Response Headers---->Set-Cookie

第二种:点击url输入框左边的信息icon,然后找到响应的域名,展开查看cookie。


第三种:设置---->高级---->内容设置---->Cookie---->查看所有cookie设置----->根据域名搜索对应的cookie信息






1.2.2 设置cookie的有效期

注意:Flask服务器默认设置cookie有效期为关闭浏览器后cookie失效

1.2.2.1 基于max_age参数设置cookie有效期

再设置cookie的调用set_cookie()时候传入关键字实参 max_age= 值,这个代表多少秒后过期。
注意:max_age参数设置过期时间不兼容IE8一下的浏览器

...
@app.route('/')
def hello_world():
resp = Response('设置cookie给浏览器')
resp.set_cookie('user_name', 'mark',max_age=60) return resp
...

1.2.2.2 基于expires参数设置cookie有效期

再设置cookie的调用set_cookie()时候传入关键字实参 expires= 值,这个代具体的过期时间,一个datetime对象或UNIX时间戳。
使用expires参数,就必须会用格林尼治时间(也就是相对北京时间少8个小时,因为浏览器会默认把服务器传来的时间值当做标准格林尼治时间,并根据当地的时区做调整

@app.route('/expires_demo/')
def expires_demo():
resp = Response('设置cookie给浏览器, cookie设置过期时间为一个月后')
expires = datetime.now()+timedelta(days=30, hours=16)
resp.set_cookie('user_name', 'mark', expires=expires)
return resp

1.2.3 在Flask中查询cookie

基于2.2.1.2 实例
查询cookie 是通过请求对象的cookies属性读取,读取的过程是使用设置cookie时的key来读取到设置cookievalue

...
@app.route('/get_cookie/')
def get_cookie():
user_name = request.cookies.get('user_name')
if user_name == 'mark':
return '{}的信息'.format(user_name) return 'cookie验证失败'
...

1.2.4删除cookie

基于2.2.1.2实例
删除cookie是通过Flask内置的Response类实例化出的对象调用delete_cookie('key'),删除的过程是使用设置cookie时的key来删除cookie信息。

@app.route('/del/')
def del_cookie():
resp = Response('删除cookie')
resp.delete_cookie('user_name')
return resp

02-session

2.1 什么是session?

session的基本概念:session又称之为安全的cookie,session是一个思路、是一个概念、一个服务器存储授权信息的解决方案,不同的服务器,不同的框架,不同的语言有不同的实现,session的目的和cookie完全一致,cookie在客户端和服务端处理的非常粗糙,cookie在浏览器保存的时候以及传输的过程均使用明文,导致了很多安全隐患问题,session的出现就是为了解决cookie存储数据不安全的问题。
注意:session是一个思路一个概念,session的实现是基于cookie的,session并不像cookie是一项真实存在的技术,可以简单的理解为把粗糙的cookie在服务端通过加密,永久化等方式提高cookie的安全级别。

2.2 实现session的两种思路

第一种

  1. 客户端携带用户信息请求服务端验证。
  2. 服务端验证成功后生成随机的session_id与用户信息建立映射后存储到数据库中(注意:数据库可以是任意永久化保存数据的机制,如redis、memcached、mysql、甚至是文件等等)。
  3. 服务端把刚刚生成的session_id作为cookie信息返回给客户端。
  4. 客户端收到以session_id为内容的cookie信息保存到本地。
  5. 客户端再次请求的时候会携带以session_id为内容的cookie去访问服务端,服务端取出session_id去数据库校验得到用户信息。


第二种

  1. 客户端携带用户信息请求服务端验证。
  2. 服务端收到用户信息验证成功后,服务端再把用户信息经过严格的加密加盐生成session信息。并且把刚刚生成的session信息作为cookie的内容返回给客户端。
  3. 客户端收到以session信息为内容的cookie保存到本地。
  4. 客户端再次请求的时候会携带以session信息为内容的cookie去访问服务端,服务端取出session信息经过解密得到用户的信息。


注意:flask使用的就是第二种思路,利用加密解密的方式实现session,实现安全的cookie,服务端并不会做永久化的储存。

2.3 如何在flask中实现session?

2.3.1 设置session

Flask提供了session对象用来将cookie加密储存,session通过秘钥对数据进行签名以加密数据。

from flask import Flask, session
import os app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) # 配置session使用的秘钥 @app.route('/')
def set_session_info():
session['username'] = 'mark' # 使用用户信息配置sesion信息作为cookie,并添加到响应体中 return '设置session信息'

解读

通过app对象 通过SECRET_KEY配置session使用的加密秘钥

app.config['SECRET_KEY'] = os.urandom(24) # 配置session使用的秘钥

session对象像可以字典一样操作,内部是把字典的信息进行加密操作然后添加到相应体中作为cookie,响应的时候会自动返回给浏览器。

session['username'] = 'mark'
session['userphone'] = '123456' # 可以指定多条session信息,统一放到响应的cookie中返回给浏览器

2.3.2 设置session有效期

后端Flask跟浏览器交互默认情况下,session cookie会在用户关闭浏览器时清除。通过将session.permanent属性设为True可以将session的有效期延长为31天,也可以通过操作app的配置PERMANENT_SESSION_LIFETIME来设置session过期时间。
案例 3.3.2.1:开启指定session过期时间模式

from flask import Flask, session
import os app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) @app.route('/')
def set_session_info():
session['username'] = 'mark'
session['userphone'] = '123456'
session.permanent = True # 开启设置有效期,默认为31天后过期
return 'Hello World!'
...


案例 3.3.2.1:开启session指定过期时间模式后指定具体的过期时间
基于案例3.3.2.1,通过设置PERMANENT_SESSION_LIFETIME指定具体的过期时间

from datetime import timedelta
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=1) # 设置为1小时候过期

2.3.3 获取session

在Flask中获取设置的session信息通过session对象获取,session对象是继承了字典类,所以获取的时候是字典的取值方式。其内部会把浏览器传过来的session信息解密。

@app.route('/get_session/')
def get_session():
username = session.get('username')
userphone = session.get('userphone')
if username or userphone:
return "{},{}".format(username, userphone)
return "session为空"

2.3.4 删除session

session对象调用pop()可以根据具体的session的key清除掉指定的session信息。
session对象调用clear()可以清除此次请求的浏览器关于本域名的所有session信息

@app.route('/del_session/')
def del_session():
session.pop('username')
# session.clear()
return '删除成功'

3.1 flask模板上下文处理器

app对象调用context_processor作为模板上下文处理器,视图函数在每一次调用render_template(‘’)的时候都会为模板传入@app.context_processor装饰器所装饰函数的返回值,该返回值作为模板变量,但是返回值一定要为字典,如果不想返回任何值,可以返回空字典,否则会报错,返回值可以设置为模板经常要使用的变量,减少了代码的冗余,提高了代码的可维护性。
实例 4.1

...

@app.route('/')
def hello_world():
context_dict = {
"username": "马克"
} return render_template('index.html', **context_dict) @app.route('/detail/')
def detail():
context_dict = {
"username": "马克"
} return render_template('detail.html', **context_dict) ...

实例4.2
实例4.2 利用模板上下文处理器避免了一些代码的冗余,利用该处理器,可以为视图函数每一次返回模板的时候传入设置好的变量,实例4.2实现的效果同实例4.1完全一致。

...

@app.route('/')
def hello_world():
return render_template('index.html') @app.route('/detail/')
def detail():
return render_template('detail.html') @app.context_processor
def context_processor():
return {"username":"马克"} ...

适用场景:比如登录网站后用户信息始终显示在页面的右上角,我们可以利用模板上下文处理器,做到每次返回模板的时候都为其传入用户信息,减少了代码的冗余,提高了代码的可维护性。

4 闪现

4.1 在模板中获取闪现信息

Flask 提供了一个非常简单的方法来使用闪现系统向用户反馈信息。闪现系统使得在一个请求结束的时候记录一个信息,然后在且仅仅在下一个请求中访问这个数据,强调flask闪现是基于flask内置的session的,利用浏览器的session缓存闪现信息。所以必须设置secret_key

4.1.1 简单的在模板中实现获取闪现信息

实例:
server.py

from flask import Flask, flash, redirect, render_template, \
request, url_for app = Flask(__name__)
app.secret_key = 'some_secret' @app.route('/')
def index():
return render_template('index.html') @app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or \
request.form['password'] != '123':
error = '登录失败'
else:
flash('恭喜您登录成功')
return redirect(url_for('index'))
return render_template('login.html', error=error) if __name__ == "__main__":
app.run()

注意:这个 flash() 就可以实现在下一次请求时候,将括号内的信息做一个缓存。不要忘记设置secret_key
这里是 index.html 模板:

{% with messages = get_flashed_messages() %}  # 获取所有的闪现信息返回一个列表
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %} <h1>主页</h1>
<p>跳转到登录页面<a href="{{ url_for('login') }}">登录?</a>

注意:{% with messages = get_flashed_messages() %} 获取所有的闪现信息返回一个列表
这里是login.html 模板

<h1>登录页面</h1>
{% if error %}
<p class=error><strong>Error:</strong> {{ error }}
{% endif %}
<form action="" method=post>
用户名:
<input type=text name=username>
密码:
<input type=password name=password>
<p><input type=submit value=Login></p>
</form>

简单的在模板中实现获取闪现信息小结:

设置闪现内容:flash('恭喜您登录成功')
模板取出闪现内容:{% with messages = get_flashed_messages() %}
4.1.2 模板中的分类闪现

当闪现一个消息时,是可以提供一个分类的。未指定分类时默认的分类为 'message' 。 可以使用分类来提供给用户更好的反馈,可以给用户更精准的提示信息体验。
要使用一个自定义的分类,只要使用 flash() 函数的第二个参数:

flash('恭喜您登录成功',"status")
flash('您的账户名为admin',"username")

在使用get_flashed_messages()时候需要传入with_categories=true便可以渲染出来类别

{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class=flashes>
{% for category, message in messages %}
<li class="{{ category }}">{{ category }}:{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}


模板中的分类闪现小结:

分类设置闪现内容:flash('恭喜您登录成功',"status")
flash('您的账户名为admin',"username")
模板取值: {% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class=flashes>
{% for category, message in messages %}
...
4.1.3 模板中过滤闪现消息

同样要使用一个自定义的分类,只要使用 flash() 函数的第二个参数:

flash('恭喜您登录成功',"status")
flash('您的账户名为admin',"username")

在使用get_flashed_messages()时候需要传入category_filter=["username"]便可根据类别取出闪现信息。中括号内可以传入的值就是类别,可以传入多个。

{% with messages = get_flashed_messages(category_filter=["username"]) %}
{% if messages %}
<ul>
{%- for message in messages %}
<li>{{ message }}</li>
{% endfor -%}
</ul>
</div>
{% endif %}
{% endwith %}


小结:

分类设置闪现内容:flash('恭喜您登录成功',"status")
flash('您的账户名为admin',"username")
模板取值: % with messages = get_flashed_messages(category_filter=["username"]) %}
{% if messages %}
<ul>
{%- for message in messages %}

4.2 在视图中获取闪现信息

4.2.1 简单的在是视图中获取闪现信息
-设置: flash('xxx')
-取值:get_flashed_message() # 注意这个不同于模板取值,这个是从flask中导入的
-注意:在视图中获取闪现信息不必非得是两次连续的请求,只要保证是第一次取相应的闪现信息,就可以取得到。

实例:

from flask import Flask, request, flash, get_flashed_messages
import os app = Flask(__name__)
app.secret_key = os.urandom(4)
app.debug = True @app.route('/login/')
def login():
if request.args.get('name') == 'rocky':
return 'ok'
flash('第一条闪现信息:用户名不是rocky填写的是{}'.format(request.args.get('name')))
# flash('第二条闪现信息:用户名不是rocky填写的是{}'.format(request.args.get('name')))
return 'error,设置了闪现'
@app.route('/get_flash/')
def get_flash():
#get_flashed_messages()是一个列表列表可以取出闪现信息,该条闪现信息只要被取出就会删除掉。
return '闪现的信息是{}'.format(get_flashed_messages()) @app.route('/demo/')
def demo():
return 'demo' if __name__ == '__main__':
app.run()

(1) 会触发设置闪现内容

(2) 取出闪现内容

(3) 再次取出闪现内容,发现闪现内容取出一次后就为空了

小结:
get_flashed_messages()是一个列表,该列表可以取出闪现信息,该条闪现信息只要被取出就会删除掉。

4.2.2 在视图中实现分类获取闪现信息。
-设置:flash('用户名错误', "username_error")
flash('用户密码错误', "password_error") # 第二个参数为闪现信息的分类。 -取所有闪现信息的类别和闪现内容:get_flashed_messages(with_categories=True) -针对分类过滤取值:get_flashed_messages(category_filter=['username_error'])
# 中括号内可以写多个分类。 -注意:如果flash()没有传入第二个参数进行分类,默认分类是 'message'

实例1

@app.route('/login/')
def login():
if request.args.get('name') == 'rocky':
return 'ok'
flash('用户名错误', category="username_error")
flash('用户密码错误', "password_error")
return 'error,设置了闪现'
@app.route('/get_flash/')
def get_flash():
return '闪现的信息是{}'.format(get_flashed_messages(with_categories=True))

把所有的闪现类别和闪现信息返回。

实例2

@app.route('/login/')
def login():
if request.args.get('name') == 'rocky':
return 'ok'
flash('用户名错误', category="username_error")
flash('用户密码错误', "password_error")
return 'error,设置了闪现'
@app.route('/get_flash/')
def get_flash():
return '闪现的信息是{}'.format(get_flashed_messages(category_filter=['username_error']))

返回页面只显示了 "username_error"的分类内容。

Flask框架——Flask脚本、flask知识点补充的更多相关文章

  1. 初识Flask框架,以及Flask中的模板语言jinjia2和Flask内置的Session

    一.web框架的对比 首先我们先来看下比较火的web框架 1.Django: 优点:大而全,所有组件都是组织内部开发高度定制化,教科书级别的框架 缺点:大到浪费资源,请求的时候需要的资源较高 2.Fl ...

  2. python --flask框架的搭建--(flask,python2,python3都可以运行)

    在linux搭建flask开发环境: (1)virtualenv -p python3 flasky                ---创建虚拟环境 (2)source flasky/bin/act ...

  3. python之Flask框架

    一.简单的Flask框架 1)flask简介 Flask 是一个 web 框架.也就是说 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序. 这个 wdb 应用程序可以使一些 we ...

  4. 初识Flask框架

    Flask简介: Flask诞生于2010年,是Armin ronacher(人名)用 Python 语言基于 Werkzeug 工具箱编写的轻量级Web开发框架. Flask 本身相当于一个内核,其 ...

  5. Flask框架知识点整合

    Flask 0.Flask简介 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收ht ...

  6. 5.flask知识点补充

    1.WTForms表单验证基本使用 flask-wtf是一个简化了WTForms操作的一个第三方库,WTForms表单的两个主要的功能jiushi就是验证用户提交数据的合法性以及渲染模板.当然还包括其 ...

  7. flask框架基础

    一 web的一些框架介绍 Flask:短小精悍,内部没有包含多少组件,但是第三方的组件是非常丰富的. Django:django是一个重武器,内部包含了非常多的组件:orm,form,modelFor ...

  8. Flask 框架入门

    Flask Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 . 安装 Flask 依赖两个外部库, We ...

  9. Flask框架搭建一个日程表

    目录 前言 项目介绍 技术栈 Flask Web开发流程 一.搭建环境 1.1: 创建虚拟环境 1.2: 安装依赖包 1.3: 创建依赖包列表文件 1.4: 测试hello word 二.应用程序开发 ...

  10. Python——Flask框架——程序的结构

    一.项目结构 |-flasky |-app Flask程序一般都保存在这里 |-templates/ |-static/ |main/ |-__init__.py |-errors.py |-form ...

随机推荐

  1. The content of element type “web-app“ must match 解决方法

    报错原因 ‍ 问题描述 : 在创建 SpringMVC 时 , 选用 idea 的 webapp 模板来创建 , xml 配置文件中进行配置时发现提示警告 警告如下: ‍ ​ ​ 这错误大概的意思就是 ...

  2. LLE算法在自然语言生成中的应用:实现文本到语音的情感迁移

    目录 自然语言生成(Natural Language Generation,NLP)是人工智能领域的一个分支,它利用大量的文本数据训练出语言模型,从而实现对自然语言的生成和理解.在NLP中,情感迁移( ...

  3. MultiscaleResNet50:AnEfficientandAccurateApproachforIma

    目录 标题:<51. Multi-scale ResNet-50: An Efficient and Accurate Approach for Image Recognition> 背景 ...

  4. 一文掌握设计模式(定义+UML类图+应用)

    一.引子 从学编程一开始就被告知,要想做一名优秀的程序员两大必要技能:1.源码阅读(JDK.C等底层语言封装) 2.设计模式(使用某种语言优雅的落地典型场景功能).一般随着工作年限的增长,被迫对底层语 ...

  5. NodeJS使用npm安装vue脚手架

    开发环境准备:Windows10.Windows11 NodeJS,安装官网最新LTS版即可 下载地址:https://nodejs.org/安装一路下一步,默认即可 ================ ...

  6. CF103B Cthulhu题解

    CF103B Cthulhu 点击查看题目 点击查看思路 如果 \(n < m\),那么会形成多个环. 如果 \(n > m\),那么不会形成环. 只有 \(n = m\) 时会形成环, ...

  7. 【调制解调】VSB 残留边带调幅

    说明 学习数字信号处理算法时整理的学习笔记.同系列文章目录可见 <DSP 学习之路>目录,代码已上传到 Github - ModulationAndDemodulation.本篇介绍 VS ...

  8. 【Python】数据可视化利器PyCharts在测试工作中的应用

    PyCharts 简介 PyCharts 是一个基于 Python 的数据可视化库,它支持多种图表类型,如折线图.柱状图.饼图等.PyCharts 提供了简洁的 API,使得用户能够轻松地创建各种图表 ...

  9. SpringBoot整合WebService(实用版)

    SpringBoot整合WebService 简介 WebService就是一种跨编程语言和跨操作系统平台的远程调用技术 此处就不赘述WebService相关概念和原理了,可以参考:https://b ...

  10. TypeScript: 類型 'HTMLElement | null' 不可指派給類型 'HTMLElement'。 類型 'null' 不可指派給類型 'HTMLElement'

    报错截图 解决方案 在结尾添加叹号 // 获取页面中food的元素并将其赋值给element this.element = document.getElementById('food')!;