Flask扩展使用笔记

2022-09-29 17:39:57 浏览数 (1)

[TOC]

Flask-Script 扩展

描述: 他是可以支持FLASK命令行参数的

使用流程:使用app创建manager对象并且启动Manager对象;

Flask-Buleprint 扩展

描述: 可以扩展路由

Flask-Migrate 扩展

描述:该扩展实现数据库字段模型迁移

  • 在Flask中像Django中一样进行模型迁移,初始化使用app 和 db 进行初始化,同时也可以使用懒加载方法

初始化需要app和数据库(SQLAlchemy)需要配置Flask-script扩展 使用在manager添加一个管理指令,manager.add_command(‘db’,MigrateCommand)

调用: python xx.py db {command}

依托于SQLAlchemy进行数据库迁移,Flask从入门到精通之使用Flask-Migrate实现数据库迁移

  • 在开发程序的过程中,你会发现有时需要修改数据库模型,而且修改之后还需要更新数据库。仅当数据库表不存在时,Flask-SQLAlchemy 才会根据模型进行创建。因此,更新表的唯一方式就是先删除旧表,不过这样做会丢失数据库中的所有数据。更新表的更好方法是使用数据库迁移框架。源码版本控制工具可以跟踪源码文件的变化,类似地,数据库迁移框架能跟踪数据库模式的变化,然后增量式的把变化应用到数据库中。
  • SQLAlchemy 的主力开发人员编写了一个迁移框架,称为Alembic(https://alembic.readthedocs.org/en/latest/index.html)。除了直接使用Alembic 之外,Flask 程序还可使用Flask-Migrate(http://flask-migrate.readthedocs.org/en/latest/)扩展。这个扩展对Alembic 做了轻量级包装,并集成到Flask-Script 中,所有操作都通过Flask-Script 命令完成。
代码语言:javascript复制
python .setup.py db -?
usage: Perform database migrations
Perform database migrations
positional arguments:
  {init,revision,migrate,edit,merge,upgrade,downgrade,show,history,heads,branches,current,stamp}
    init                Creates a new migration repository
    revision            Create a new revision file.
    migrate             Alias for 'revision --autogenerate'
    edit                Edit current revision.
    merge               Merge two revisions together. Creates a new migration
                        file
    upgrade             Upgrade to a later version
    downgrade           Revert to a previous version
    show                Show the revision denoted by the given symbol.
    history             List changeset scripts in chronological order.
    heads               Show current available heads in the script directory
    branches            Show current branch points
    current             Display the current revision for each database.
    stamp               'stamp' the revision table with the given revision;dont run any migrations

optional arguments:
  -?, --help            show this help message and exit

# 初始化
python .setup.py db init
Creating directory E:githubProjectStudy-PromgramPython3FlaskDay2migrations ...  done
Creating directory E:githubProjectStudy-PromgramPython3FlaskDay2migrationsversions ...  done
Generating E:githubProjectStudy-PromgramPython3FlaskDay2migrationsalembic.ini ...  done
Generating E:githubProjectStudy-PromgramPython3FlaskDay2migrationsenv.py ...  done
Generating E:githubProjectStudy-PromgramPython3FlaskDay2migrationsREADME ...  done
Generating E:githubProjectStudy-PromgramPython3FlaskDay2migrationsscript.py.mako ...  done
Please edit configuration/connection/logging settings in 'E:\githubProject\Study-Promgram\Python3\Flask\Day2\migrations\alembic.ini' before proceeding.   

# 迁移
python .setup.py db migrate
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'member'
INFO  [alembic.autogenerate.compare] Detected added table 'user'
Generating E:githubProjectStudy-PromgramPython3FlaskDay2migrationsversions3e14bc22cd7_.py ...  done

# 更新
PS E:githubProjectStudy-PromgramPython3FlaskDay2> python .setup.py db upgrade
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 03e14bc22cd7, empty message
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added column 'member.age'
Generating E:githubProjectStudy-PromgramPython3FlaskDay3migrationsversions881b583153df_.py ...  done

PS E:githubProjectStudy-PromgramPython3FlaskDay3> python .Setup.py db upgrade
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade 849e0b98a81c -> 881b583153df, empty message

# 查看标识版本
PS E:githubProjectStudy-PromgramPython3FlaskDay3> python .Setup.py db downgrade --tag "Revert previous version"       
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running downgrade 881b583153df -> 849e0b98a81c, empty message
Flask-Session 扩展

描述:其实现了将服务器端生成session数据存储在指定的关系型、菲关系、磁盘文件中并将对应的key的HASH存储在网页的Cookie中;

关系型数据库关系越复杂性能越低,非关系型数据库由于采用key-value形式没有级联所以效率高(通过hash表确定Key);

flask-session环境安装

代码语言:javascript复制
pip install flask-session
pip install redis

例如.存储在redis之中cookie是以hash为key,其反序列化字符串为内容;

代码语言:javascript复制
# (1) 网页中响应的cookie
session=b2af4f33-09b2-4fe4-8cec-fcefe6af2d54; Expires=Sat, 17-Oct-2020 08:34:56 GMT; Secure; HttpOnly; Path=/
# (2) Redis中b2af4f33-09b2-4fe4-8cec-fcefe6af2d54哈希存储内容 (注意前缀)
> get developb2af4f33-09b2-4fe4-8cec-fcefe6af2d54
�}q(X
_permanentq�XnameqXWeiyiGeek-RedisqXusernameqX唯一极客qu.
> ttl developb2af4f33-09b2-4fe4-8cec-fcefe6af2d54
2678272

采用Redis进行存储session的app.config的常规配置:

代码语言:javascript复制
app.config['SECRET_KEY'] = "WeiyiGeek"
app.config['SESSION_TYPE']  = 'redis'
app.config['SESSION_REDIS']  = Redis(host='10.10.172.10', password='0000',db=1)
app.config['SESSION_KEY_PREFIX']  = "develop:"
app.config['SESSION_USER_SIGNER']  = True    # 会话用户签名者加入salt与客户端的hmac
app.config['SESSION_COOKIE_SECURE']  = True

基础实例:

代码语言:javascript复制
from flask import Flask
from flask import session
from flask_session import Session
from redis import Redis

app = Flask(__name__)
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = Redis(host='192.168.100.10', password='000000',db=3)
Session(app)


@app.route('/index1')
def index():
    ret = session.items()
    print(ret)
    return 'index1'


@app.route('/index2')
def index2():
    session.update({'a':123})
    return 'index2'

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

WeiyiGeek.db3

Flask-Bootstrap 扩展

描述: 将Bootstrap3集成到Flask中我们可以以block的形式进行继承扩充, 并且带有分页、兼容IE等等视图标签函数

参考地址: https://flask-bootstrap-zh.readthedocs.io/zh/latest/basic-usage.html#id2 项目地址:https://github.com/mbr/flask-bootstrap/

安装使用:

代码语言:javascript复制
pip install flask-bootstrap

# 开始前第一步是导入和加载扩展
from flask import Flask
from flask_bootstrap import Bootstrap

def create_app():
  app = Flask(__name__)
  Bootstrap(app)

  return app

示例程序:

代码语言:javascript复制
{%- extends "bootstrap/base.html" %}

{# 网页标题设置带有默认标题 #}
{% block title %}Sample App for Flask-Bootstrap{% endblock %}

{# 在做这些工作的同时,我们还支持对旧浏览器的修复,采用宏函数进行实现 #}
{% import "bootstrap/fixes.html" as fixes %}


{% block head %}
{{super()}}
{#- Docs: http://pythonhosted.org/Flask-Bootstrap/macros.html#fixes
   The sample application already contains the required static files. #}
{{fixes.ie8()}}
{%- endblock %}

{# Adding our own CSS files is also done here. Check the documentation at
   http://pythonhosted.org/Flask-Bootstrap/basic-usage.html#available-blocks
   for an overview. #}
{% block styles -%}
    {{super()}}  {# do not forget to call super or Bootstrap's own stylesheets
                    will disappear! #}
    <link rel="stylesheet" type="text/css"
          href="{{url_for('static', filename='sample-app.css')}}">
{% endblock %}

{# Finally, round things out with navigation #}
{% block navbar %}
  {{nav.frontend_top.render()}}
{% endblock %}

Flask-Debugtoolbar 扩展

描述:Flask开发帮助工具插件Flask-Debugtoolbar它是从Django中借鉴的样式基本一致;

安装

代码语言:javascript复制
pip install Flask-Debugtoolbar

使用

代码语言:javascript复制
# Day3Appext.py
import DebugToolbarExtension
....

# 在第三方插件初始化的时候加载
def init_ext(app):
  ...
  DebugToolbarExtension(app)      # 在ext.py中进行初始化

![WeiyiGeek.DebugToolbar蓝图�https://cdn.jsdelivr.net/gh/WeiyiGeek/blogimageraw/masterek/blogimage/2020/1/20201011220828.png)

入坑与出坑: 问题1.ValueError: path is on mount ‘c:’, start on mount ‘D:’ 问题描述: 使用Flask-DebugToolbar包后,报错win10 Flask-DebugToolbar ValueError: path is on mount ‘c:’, start on mount ‘D:’

代码语言:javascript复制
File "D:Program Files (x86)Python37-32libntpath.py", line 562, in relpath
  [Open an interactive python shell in this frame] path_drive, start_drive))

问题原因: 有些包从C盘导人到了项目之中,可以通过print(sys.path)查看系统中Python环境目录C:UsersWEIYIG~1AppDataRoamingPythonPython37site-packages

解决办法:

1.暂停项目

2.删除C盘中的site-packages模块使得不从C盘导包C:UsersWEIYIG~1AppDataRoamingPythonPython37site-packages

代码语言:javascript复制
del /Q /S C:UsersWEIYIG~1AppDataRoamingPythonPython37site-packages*
Flask-caching 扩展

官网: https://pythonhosted.org/Flask-Caching/

Q: 什么是Flask-caching扩展? 它有何作用?

答: Flask-caching是Flask的一个扩展为各种后端添加缓存支持到任何Flask应用程序。除了通过统一的API提供对所有werkzeug支持的缓存后端的支持外,还可以通过子类化来开发自己的缓存后端; 简单的说它是用于后端数据缓存的例如redis的数据缓存;

扩展安装:

代码语言:javascript复制
# 方式1
$ easy_install Flask-Caching
# 方式2
$ pip install Flask-Caching

基础配置:

代码语言:javascript复制
from flask import Flask
from flask_caching import Cache

app = Flask(__name__)
cache = Cache(app, config={'CACHE_TYPE': 'simple'})

# 采用后初始化懒加载的方式
def init_ext(app):
  .....
  cache.init_app(app)

# ------------------------------ # 
# 还可以提供备用的配置:
#: Method A: During instantiation of class
cache = Cache(config={'CACHE_TYPE': 'simple'})
#: Method B: During init_app call
cache = Cache()
cache.init_app(app, config={'CACHE_TYPE': 'simple'})

简单使用:

代码语言:javascript复制
# cache 缓存设置在视图@router装饰与函数定义之间;
@app.route('/')
@cache.cached(timeout=50)
def index():
    return 'Cached for 50s'

缓存配置参数

CACHE_TYPE :指定要使用的缓存对象的类型。

代码语言:javascript复制
# 内置缓存类型
null: NullCache (default)
simple: SimpleCache  - 常用
filesystem: FileSystemCache
redis: RedisCache (Werkzeug >= 0.7 and redis required) - 常用
uwsgi: UWSGICache (Werkzeug >= 0.12 and uwsgi required)
memcached: MemcachedCache (pylibmc or memcache required)
gaememcached: GAEMemcachedCache
saslmemcached: SASLMemcachedCache (pylibmc required)
spreadsaslmemcached: SpreadSASLMemcachedCache (pylibmc required)

CACHE_NO_NULL_WARNING : 在使用缓存类型为“null”时沉默警告消息。

  • CACHE_ARGS : 可选列表,用于在缓存类实例化期间解包和传递。
  • CACHE_OPTIONS : 在缓存类实例化期间传递的可选字典。
  • CACHE_DEFAULT_TIMEOUT : 如果没有指定超时时使用的默认超时()时间单位是秒。
  • CACHE_KEY_PREFIX : 在所有键之前添加的前缀, 这使得对不同的应用程序使用相同的memcached服务器成为可能
  • CACHE_UWSGI_NAME:要连接的uwsgi缓存实例的名称,例如: mycache@localhost:3031
  • CACHE_MEMCACHED_SERVERS : 仅用于MemcachedCache服务器地址的列表或元组。
  • CACHE_MEMCACHED_USERNAME : 仅用于MemcachedCache的用户
  • CACHE_MEMCACHED_PASSWORD : 仅用于MemcachedCache的密码
  • CACHE_REDIS_HOST : A Redis server host. Used only for RedisCache.
  • CACHE_REDIS_PORT : A Redis server port. Default is 6379. Used only for RedisCache.
  • CACHE_REDIS_PASSWORD : A Redis password for server. Used only for RedisCache.
  • CACHE_REDIS_DB : A Redis db (zero-based number index). Default is 0. Used only for RedisCache.
  • CACHE_REDIS_URL : Used only for RedisCache. URL to connect to Redis server. Example redis://user:password@localhost:6379/2.
  • CACHE_DIR : 仅用于FileSystemCache。

常用API方法 这个类是用来控制缓存对象:class flask_caching.Cache(app=None, with_jinja2_ext=True, config=None)

  • init_app 方法: init_app(app, config=None)应用程序对象初始化缓存
  • cached 方法 : cached(timeout=None, key_prefix=’view/%s’, unless=None, forced_update=None, query_string=False)
  • get 方法 : get(*args, **kwargs)
  • get_many 方法 : get_many(*args, **kwargs)
  • add 方法 : add(*args, **kwargs) Proxy function for internal cache object.
  • set 方法 : set(*args, **kwargs) Proxy function for internal cache object.
  • set_many 方法 : set_many(*args, **kwargs) Proxy function for internal cache object.
  • clear 方法 : 清空缓存
  • delete 方法 : delete(*args, **kwargs) 删除指定key缓存;
  • delete_many 方法 : delete_many(*args, **kwargs) 内部缓存对象的代理函数。
  • delete_memoized 方法 : delete_memoized(f, *args, **kwargs)

使用案例

1.临时缓存删除与清空

代码语言:javascript复制
# 1.删除指定键
# 如果提供的键,你可以很容易生成模板片段密钥,并从模板上下文之外将其删除:
from flask_caching import make_template_fragment_key
key = make_template_fragment_key("key1", vary_on=["key2", "key3"])
cache.delete(key)


# 2.清空应用程序缓存
from flask_caching import Cache
....
cache = Cache()

def main():
    cache.init_app(app, config={'CACHE_TYPE': 'simple'})
    with app.app_context(): 
        cache.clear()   # 关键函数

if __name__ == '__main__':
    main()

注意事项:一些后端实现不支持完全清除缓存。此外如果你没有使用键前缀,一些实现(例如Redis)将刷新整个数据库。确保没有在缓存数据库中存储任何其他数据。

2.将数据查询到的结果进行缓存并在一段内不会失效;

代码语言:javascript复制
# 注意需要进行导包
from App.ext import cache
from sqlalchemy import and_,or_,not_

@d3.route('/logicalcache/')
@cache.cached(timeout=50)
def get_locgical_cache():
  print("首次进入将被缓存....")
  fdog = FDog.query.filter(not_(or_(FDog.id.__eq__(12),FDog.comment.contains('12'),FDog.fid.__eq__(99))))
  return render_template('cache.html',title="Flash-cache 与 逻辑运算符实践!", result=fdog)

执行结果:

WeiyiGeek.flask-cache

0 人点赞