跳转到主要内容

在TurboGears2项目中插入应用程序和扩展

项目描述

关于可插入应用程序

tgext.pluggable 允许在TG项目中插入扩展和应用程序,就像Django应用程序一样。

安装

tgext.pluggable 可以从pypi或从bitbucket安装

pip install tgext.pluggable

对大多数用户来说应该可以正常工作

插入应用程序

在您的应用程序 config/app_cfg.py 中导入 plug

from tgext.pluggable import plug

然后在 文件末尾 调用 plug 为您想要启用的每个可插入应用程序(package_name 必须已安装在你的Python环境中)

plug(base_config, 'package_name')

plug 函数接受各种可选参数,例如,如果插入的应用程序公开了一个控制器,您可以在不同的位置将其挂载,指定不同的 appid

plug(base_config, 'package_name', 'new_app_id')

如果您想将可插入应用程序挂载到子控制器中,可以使用点号 appid,例如 subcontroller.appid。注意,subcontroller 必须存在于RootController中。

其他选项包括

  • plug_helpers (True/False) -> 启用助手注入

  • plug_models (True/False) -> 启用模型插入

  • plug_controller (True/False) -> 挂载可插入应用程序根控制器

  • plug_bootstrap (True/False) -> 启用 websetup.bootstrap 插件

  • plug_statics (True/False) -> 启用插件应用的静态文件

  • rename_tables (True/False) -> 通过添加 appid 重命名插件表

与插件应用模型的关联

有些情况下,您可能需要与由插件应用定义的模型创建关系或外键。由于插件应用模型是在加载您的应用之后加载的,因此在导入应用模型时它们不可用。

tgext.pluggable 提供了一些实用工具,以简化与插件应用定义的模型创建关系的过程。

您可能想要采取的第一步是将 global_models=True 参数设置到 plug 调用中,这将使所有由插件应用声明的模型都可供您使用

plug(base_config, 'package_name', global_models=True)

在指定的插件应用被插入后,模型将通过 tgext.pluggable.app_model 对象在您的代码中可用。

然后,您可以使用 tgext.pluggable.LazyForeignKey 类创建到所需模型的外键,并使用 sqlalchemy.orm.relation 的延迟版本声明关系

from tgext.pluggable import app_model, LazyForeignKey

class AdditionalInfo(DeclarativeBase):
    __tablename__ = 'sample_model'

    uid = Column(Integer, primary_key=True)
    data = Column(Unicode(255), nullable=False)

    plugged_model_id = Column(Integer, LazyForeignKey(lambda:app_model.PluggedModel.uid))
    plugged_model = relation(lambda: app_model.PluggedModel)

部分

tgext.pluggable 提供了一组用于处理部分的实用工具。在 tgext.pluggable 中,部分可以声明为具有 @expose 装饰器的函数或 TGController 子类方法。这些部分可以通过以下方式渲染

${h.call_partial('module:function_name', arg1='Something')}

在类方法的情况下

${h.call_partial('module.Class:method', arg1='Something')}

快速入门的插件应用提供了一个示例部分

from tg import expose

@expose('plugappname.templates.little_partial')
def something(name):
    return dict(name=name)

该部分可以通过以下方式渲染

${h.call_partial('plugappname.partials:something', name='Partial')}

替换模板

tgext.pluggable 提供了一个替换模板的函数。这在您想覆盖已插入应用公开的模板时非常有用。要在应用配置中覆盖,请调用 replace_template

from tgext.pluggable import replace_template

replace_template(base_config, 'myapp.templates.about', 'myapp.templates.index')

replace_template 即使在 tgext.pluggable 部分中也能正常工作,但不会直接调用 render 方法渲染的模板。

必须在应用程序启动之前执行对 replace_template 的调用。

修补模板

tgext.pluggable 提供了一个修补模板的函数,模板渲染的结果将通过一系列操作传递,这将使得改变渲染结果成为可能。

这种行为很大程度上受到了 Deliverance http://pythonhosted.org/Deliverance 的启发,它适用于更简单的用例。最常见的用法是修改插件应用模板的小改动。对于更高级的操纵,建议使用 replace_template,因为它既快又易于维护。

使用 load_template_patches 函数启用模板修补

from tgext.pluggable import load_template_patches

load_template_patches(base_config)

假设您的项目位于名为 myapp 的 Python 发行版中,这将从发行版的根目录加载 template_patches.xml 文件,并将应用所有指定的修补程序。

要从 Python 模块(或插件)加载模板修补程序,使用以下方法

load_template_patches(base_config, 'plugname')

您甚至可以使用前面的表达式来从您的应用程序加载修补程序,以防发行版的自动检测失败。

模板修补程序格式是形式为 xml 的文件

<patches>
  <patch template="tgext.crud.templates.get_all">
    <content selector="#crud_content > h1" template="myapp.templates.replacements.crud_title" />
    <append  selector="#crud_content > h1" template="myapp.templates.replacements.crud_subtitle" />
    <prepend selector="#crud_content > h1" template="myapp.templates.replacements.crud_superscript" />
    <replace selector="#crud_btn_new > .add_link" template="" />
  </patch>
</patches>

修补程序中列出的每个操作将在指定模板被渲染时执行,与操作关联的模板将用作模板的内容,并且修补模板可用的相同数据也将可用于操作模板。可用的操作有

  • content - 替换由选择器标识的标签的内容

  • append - 在由选择器标识的标签之后附加

  • prepend - 在由选择器标识的标签之前添加

  • replace - 替换由选择器识别的标签。

创建可插拔应用

tgext.pluggable 提供了一个 quickstart-pluggable 命令来创建一个新的可插拔应用。

$ gearbox quickstart-pluggable plugtest
Enter package name [plugtest]:
...

快速启动的应用将提供一个示例,展示如何使用模型、辅助器、引导、控制器和静态资源。

在前一个示例中,可以使用以下命令在 TurboGears 中启用可插拔应用:

plug(base_config, 'plugtest')

启用 plugtest 应用后,应在 TurboGears 项目中运行 gearbox setup-app 以创建示例模型。然后您可以通过 http://localhost:8080/plugtest 访问示例应用页面。

plugme 入口点

可插拔应用需要实现一个 plugme(app_config, options) 入口点,当插入应用时会被调用。

plugme 动作在 TurboGears 配置加载之前被调用,因此可以在 plugme 钩子内部注册更多可插拔应用。这样,可插拔应用可以通过在其自己的 plugme 函数内部调用 tgext.pluggable.plug 来插入它需要的任何依赖。

传递给 plug 调用的任何选项都将在 options 字典中可用,其他可插拔应用的部分(如控制器、模型等)将在调用 plugme 之后导入,这样 plugme 可以设置任何配置选项,这些选项将驱动其他部分的行为。

请注意,由于 plugme 在加载 TurboGears 配置之前被调用,如果您需要根据任何配置文件选项执行某些操作,您必须在 plugme 调用中注册一个 setup 并在那里执行它们。

更改静态文件行为

默认情况下,每个可插拔应用都会按照原样服务其公共目录中可用的所有静态文件。这是通过一个负责服务静态文件的 WSGI 应用程序来执行的。从版本 0.2.1 开始,现在可以通过 static_middlewares 选项替换此应用程序或对其应用任何 WSGI 中间件。

例如,您可以通过定义一个 plugme 函数来在您的可插拔应用中启用 SCSS:

from tgext.scss import SCSSMiddleware

def plugme(app_config, options):
    return dict(appid='plugtest', global_helpers=False, static_middlewares=[SCSSMiddleware])

从可插拔应用访问应用模型

在创建可插拔应用时,您可能经常需要访问目标应用中声明的某些模型,其中可插拔应用将被挂载。

这种情况最常见的是引用用户、组和权限模型。为此,tgext.pluggable 提供了一个 app_model 对象,它包装了应用模型,并在加载可插拔应用之前初始化。

这使得通过将它们引用为 app_model.Userapp_model.Group 等,来访问目标应用模型成为可能。虽然您可能已经猜到这些模型的键是已知的(例如,对于 app_model.User 对象,您可能将其引用为 app_model.User.user_id),但最好使用 tgext.pluggable 提供的 primary_key 函数来获取其列的引用。

这样就可以声明与您的可插拔应用不提供的模型的关系。

from tgext.pluggable import app_model, primary_key

user_id = Column(Integer, ForeignKey(primary_key(app_model.User)))
user = relation(app_model.User)

可插拔相对 URL

可以使用 plug_url(pluggable, path, params=None, lazy=False) 函数生成相对于可插拔挂载点的 URL。当使用可插拔时,此函数也暴露在应用程序辅助器中。例如,要生成相对于 plugtest 可插拔的 URL,您可以调用 plug_url:

plug_url('plugtest', '/')

要在一个可插拔应用内部执行重定向,提供了 plug_redirect(pluggable, path, params=None) 函数。此函数与 plug_url 具有相同的接口,但执行重定向的方式类似于 tg.redirect。

国际化

tgext.pluggable 提供了一些用于在可插拔应用中管理文本翻译的实用程序。当使用 tg.i18n.ugettexttg.i18n.lazy_ugettext 时,它们将在应用程序中查找翻译,当不可用时会回退到可插拔本身提供的翻译。

使用 Babel 对 TurboGears 中的可插入工作执行消息提取和目录创建/更新。只需在可插入应用程序内部运行 python setup.py extract_messagespython setup.py init_catalog -l LANGpython setup.py compile_catalog 命令以创建 LANG 的目录。

只需将目录与您的可插入应用程序一起分发,以便在使用它的应用程序中可用并翻译。

迁移管理

可以为可插入应用程序初始化迁移存储库。这使得在以后的时间使用 SQLAlchemy 的 alembic 迁移库对每个可插入应用程序进行数据库升级成为可能。

创建迁移存储库

要能够管理迁移,可插入应用程序必须使用迁移存储库进行初始化,为此,可插入应用程序的作者必须运行

$ gearbox migrate-pluggable plugtest init

然后,要创建迁移脚本,请运行

$ gearbox migrate-pluggable plugtest create 'Add column for user_name'

一个名为 2c8c79324a5e_Add_column_for_user_name.py 的文件将出现在可插入应用程序的 migration/versions 目录中。请记住将此目录添加到您的分发包中,以便可供您的可插入应用程序用户使用

使用迁移

如果您使用的可插入应用程序支持迁移,则可以使用 upgradedowngrade 命令应用它们。

可以通过运行 upgrade 来向前移动

$ gearbox migrate-pluggable plugtest upgrade
22:11:28,029 INFO  [alembic.migration] Running upgrade None -> 3ca22a16fdcc

或运行 downgrade 来撤销迁移

$ gearbox migrate-pluggable plugtest downgrade
22:15:24,004 INFO  [alembic.migration] Running downgrade 3ca22a16fdcc -> None

版本命令支持通过指定 all 作为可插入名称来对应用程序中启用的所有可插入进行调用。这将加载您的应用程序以检测已插入的应用程序,并为每个应用程序运行指定的命令

$ gearbox migrate-pluggable all db_version
22:15:54,104 INFO  [tgext.pluggable] Plugging plug1
22:15:54,105 INFO  [tgext.pluggable] Plugging plug2
22:15:54,106 INFO  [tgext.pluggable] Plugging plug3
Migrating plug1, plug3, plug2

plug1 Migrations
    Repository '/tmp/PLUGS/plug1/migration'
    Configuration File 'development.ini'
    Versioning Table 'plug1_migrate'
22:15:54,249 INFO  [alembic.migration] Context impl SQLiteImpl.
22:15:54,249 INFO  [alembic.migration] Will assume transactional DDL.
Current revision for sqlite:////tmp/provaapp/devdata.db: 4edef05cc346 -> 1ae930148d69 (head), fourth migration

plug3 Migrations
    Repository '/tmp/PLUGS/plug3/migration'
    Configuration File 'development.ini'
    Versioning Table 'plug3_migrate'
22:15:54,253 INFO  [alembic.migration] Context impl SQLiteImpl.
22:15:54,254 INFO  [alembic.migration] Will assume transactional DDL.
Current revision for sqlite:////tmp/provaapp/devdata.db: 15819683bb72 -> 453f571f41e4 (head), test migration

plug2 Migrations
    Repository '/tmp/PLUGS/plug2/migration'
    Configuration File 'development.ini'
    Versioning Table 'plug2_migrate'
22:15:54,258 INFO  [alembic.migration] Context impl SQLiteImpl.
22:15:54,259 INFO  [alembic.migration] Will assume transactional DDL.
Current revision for sqlite:////tmp/provaapp/devdata.db: 154b4f69cbd1 -> 2c8c79324a5e (head), third migration

支持者:

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面