笨鸟编程-零基础入门Pyhton教程

 找回密码
 立即注册

Flask 扩展开发

发布者: 笨鸟自学网



flask_sqlite3.py

现在这个是你的扩展放代码的位置。但是这样一个扩展到底看起来是什么样? 最佳实践是什么?继续阅读,你会有一些认识。

初始化扩展

许多扩展会需要某种类型的初始化步骤。比如,想象一个应用像文档中建议的一样 (在 Flask 中使用 SQLite 3) 正在连接到 SQLite。那么,扩展如何获知应用对象的名称?

相当简单:你传递应用对象到它。

有两种推荐的初始化应用的方式:

初始化函数:

如果你的扩展叫做 helloworld ,你应该有一个名为 init_helloworld(app[, extra_args]) 的函数来为应用初始化扩展。它 可以附加在处理器前/后等位置。
类:
类的工作大多像初始化函数,但可以在之后进一步更改其行为。例如 OAuth 扩展 的工作方式,一个 OAuth 对象提供一些诸如 OAuth.remote_app 的助手函数来创建一个使用 OAuth 的远程应用的引用。

用什么取决于你想要什么。对于 SQLite 3 扩展,我们会使用基于类的方法,因为它 提供用户一个可以承担打开和关闭数据库连接的对象。

关于类,重要的是它们鼓励在模块层内共享。这种情况下,对象本身在任何情况下 不得存储任何应用的特定状态,而必须可以在不同的应用间共享。

扩展的代码

下面是用来复制/粘贴的 flask_sqlite3.py 的内容:

import sqlite3
from flask import current_app

# Find the stack on which we want to store the database connection.
# Starting with Flask 0.9, the _app_ctx_stack is the correct one,
# before that we need to use the _request_ctx_stack.
try:
    from flask import _app_ctx_stack as stack
except ImportError:
    from flask import _request_ctx_stack as stack


class SQLite3(object):

    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        app.config.setdefault('SQLITE3_DATABASE', ':memory:')
        # Use the newstyle teardown_appcontext if it's available,
        # otherwise fall back to the request context
        if hasattr(app, 'teardown_appcontext'):
            app.teardown_appcontext(self.teardown)
        else:
            app.teardown_request(self.teardown)

    def connect(self):
        return sqlite3.connect(current_app.config['SQLITE3_DATABASE'])

    def teardown(self, exception):
        ctx = stack.top
        if hasattr(ctx, 'sqlite3_db'):
            ctx.sqlite3_db.close()

    @property
    def connection(self):
        ctx = stack.top
        if ctx is not None:
            if not hasattr(ctx, 'sqlite3_db'):
                ctx.sqlite3_db = self.connect()
            return ctx.sqlite3_db

那么这是这些代码做的事情:

  1. __init__ 方法接受一个可选的应用对象,并且如果提供,会调用 init_app 。

  2. init_app 方法使得 SQLite3 对象不需要应用对象就可以实例化。这个方法 支持工厂模式来创建应用。 init_app 会为数据库设定配置,如果不提供配置,默 认是一个内存中的数据库。此外, init_app 方法附加了 teardown 处理器。 它会试图使用新样式的应用上下文处理器,并且如果它不存在,退回到请求上下文处理 器。

  3. 接下来,我们定义了 connect 方法来打开一个数据库连接。

  4. 最后,我们添加一个 connection 属性,首次访问时打开数据库连接,并把它存储 在上下文。这也是处理资源的推荐方式:在资源第一次使用时惰性获取资源。

    注意这里,我们把数据库连接通过 _app_ctx_stack.top 附加到应用上下文 的栈顶。扩展应该使用上下文的栈顶来存储它们自己的信息,并使用足够复杂的 名称。注意如果应用使用不支持它的老版本的 Flask 我们退回到 _request_ctx_stack.top 。

那么为什么我们决定在此使用基于类的方法?因为使用我们的扩展的情况看起来 会是这样:

from flask import Flask
from flask_sqlite3 import SQLite3

app = Flask(__name__)
app.config.from_pyfile('the-config.cfg')
db = SQLite3(app)

你之后可以在视图中这样使用数据库:

@app.route('/')
def show_all():
    cur = db.connection.cursor()
    cur.execute(...)

同样地,如果你在请求之外,而你在使用支持应用上下文 Flask 0.9 或之后的版本, 你可以用同样的方法使用数据库:

with app.app_context():
    cur = db.connection.cursor()
    cur.execute(...)

在 with 块的最后,销毁处理器会自动执行。

此外, init_app 方法用于支持创建应用的工厂模式:

db = Sqlite3()
# Then later on.
app = create_app('the-config.cfg')
db.init_app(app) 

Archiver|手机版|笨鸟自学网 ( 粤ICP备20019910号 )

GMT+8, 2024-12-22 00:26 , Processed in 0.050143 second(s), 17 queries .

© 2001-2020

返回顶部