基本布局

由cookiecutter生成的启动文件非常基础,但它们为大多数常见的高级模式提供了良好的方向。 traversal 基于(和) ZODB 基于) Pyramid 项目。

应用程序配置 __init__.py

磁盘上的目录可以转换为python package 通过包含 __init__.py 文件。即使是空的,也会将目录标记为python包。我们使用 __init__.py 两者都是一个标记,指示包含它的目录是一个包,并包含应用程序配置代码。

当您使用 pserve 命令使用 development.ini 生成的配置文件,应用程序配置指向 Setuptools entry point 描述为 egg:tutorial . 在我们的应用程序中,因为应用程序 setup.py 文件说,这个入口点恰好是 main 名为的文件中的函数 __init__.py .

正常开放 tutorial/__init__.py . 它应该已经包含以下内容:

 1from pyramid.config import Configurator
 2from pyramid_zodbconn import get_connection
 3
 4from .models import appmaker
 5
 6
 7def root_factory(request):
 8    conn = get_connection(request)
 9    return appmaker(conn.root())
10
11
12def main(global_config, **settings):
13    """ This function returns a Pyramid WSGI application.
14    """
15    with Configurator(settings=settings) as config:
16        config.include('pyramid_chameleon')
17        config.include('pyramid_tm')
18        config.include('pyramid_retry')
19        config.include('pyramid_zodbconn')
20        config.include('.routes')
21        config.set_root_factory(root_factory)
22        config.scan()
23    return config.make_wsgi_app()

让我们一块一块地来看看。首先,我们需要一些导入来支持后面的代码。

1from pyramid.config import Configurator
2from pyramid_zodbconn import get_connection
3
4from .models import appmaker
5
6

定义一个 root factory 为我们的Pyramid应用。它建立了与zodb数据库的连接。它返回一个 appmaker ,我们将在下一节中介绍 资源和模型 models 包 .

7def root_factory(request):
8    conn = get_connection(request)
9    return appmaker(conn.root())

__init__.py 定义名为的函数 main . 以下是整个 main 我们在我们的 __init__.py

12def main(global_config, **settings):
13    """ This function returns a Pyramid WSGI application.
14    """
15    with Configurator(settings=settings) as config:
16        config.include('pyramid_chameleon')
17        config.include('pyramid_tm')
18        config.include('pyramid_retry')
19        config.include('pyramid_zodbconn')
20        config.include('.routes')
21        config.set_root_factory(root_factory)
22        config.scan()
23    return config.make_wsgi_app()

当你调用 pserve development.ini 命令 main 执行上述功能。它接受一些设置并返回 WSGI 应用。见 启动 更多关于 pserve .

下一个 main 构建一个 Configurator 使用上下文管理器的对象。也见 Deployment settings .

15    with Configurator(settings=settings) as config:

settings 传递给 Configurator 作为关键字参数,字典值作为 **settings 参数。这将是从 .ini 文件,其中包含与部署相关的值,例如 pyramid.reload_templateszodbconn.uri 等等。

接下来包括对 Chameleon 模板呈现绑定,允许我们使用 .pt 模板。

16        config.include('pyramid_chameleon')

下一个包括支持 pyramid_tm ,允许Pyramid请求加入由提供的活动事务 transaction 包。

17        config.include('pyramid_tm')

下一个包括支持 pyramid_retry 在出现暂时异常时重试请求。

18        config.include('pyramid_retry')

下一个包括支持 pyramid_zodbconn ,提供 ZODB 以及Pyramid应用程序。

19        config.include('pyramid_zodbconn')

下一个包含来自 .routes 模块。

20        config.include('.routes')

接下来,使用名为 root_factory .

21        config.set_root_factory(root_factory)

包含的模块包含以下功能。

1def includeme(config):
2    config.add_static_view('static', 'static', cache_max_age=3600)

这将使用 pyramid.config.Configurator.add_static_view() 方法。此视图回答URL路径以开头的请求 /static . 此语句注册一个视图,该视图将服务于Static Assets,如CSS和图像文件。在这种情况下,URL将在 http://localhost:6543/static/ 下面。

第一个参数是“名称” static ,表示视图的URL路径前缀将为 /static .

这个方法的第二个参数是“path”。是个亲戚 asset specification . 它会在 static 目录 tutorial 包。或者,烹饪者可以使用 绝对的 作为路径的资产规范 (tutorial:static

第三个参数是可选的 cache_max_age 它指定Static Assets将被HTTP缓存的秒数。

回到我们的 __init__.py ,下一步执行 scan .

22        config.scan()

扫描会发现 configuration decoration ,例如视图配置装饰器(例如, @view_config )在源代码中 tutorial 包。它将根据这些装饰器采取行动。我们不向 scan() ,这意味着扫描应该在当前包中进行(在这种情况下, tutorial )厨艺师也可以这么说 config.scan('tutorial') ,但它选择省略package name参数。

最后使用 pyramid.config.Configurator.make_wsgi_app() 返回的方法 WSGI 应用。

23    return config.make_wsgi_app()

资源和模型 models

Pyramid 使用单词 resource 描述在 resource tree . 这棵树是由 traversal 将URL映射到代码。在此应用程序中,资源树表示站点结构,但它 also 代表 domain model 应用程序的。每个资源都是一个持久存储在 ZODB 数据库。这个 models.py 文件是 zodb CookiCutter将实现我们的资源对象的类放在一起,每个类恰好也是一个域模型对象。

这是来源 models.py

 1from persistent.mapping import PersistentMapping
 2
 3
 4class MyModel(PersistentMapping):
 5    __parent__ = __name__ = None
 6
 7
 8def appmaker(zodb_root):
 9    if 'app_root' not in zodb_root:
10        app_root = MyModel()
11        zodb_root['app_root'] = app_root
12    return zodb_root['app_root']
  1. Lines 4-5 . 这个 MyModel resource 类在此处实现。此类的实例能够在 ZODB 因为类继承自 persistent.mapping.PersistentMapping 类。这个 __parent____name__traversal 协议。默认情况下,这些设置为 None 表示这是 root 对象。

  2. Lines 8-12 . appmaker 用于返回 应用程序根 对象。它被召唤 每一个要求Pyramid 凭借 root_factory 定义在我们的 __init__.py . 它还执行引导 创建 一个应用程序根目录(在zodb根目录对象中),如果该根目录不存在。

    引导是通过首先查看数据库是否具有持久的应用程序根来完成的。如果没有,那么我们创建一个实例,存储它,并提交事务。

    然后返回应用程序根对象。

通过查看声明 views

我们的cookiecutter生成了一个默认值 views 代表我们打包。它包含两个视图。

第一个视图用于呈现访问URL时显示的页面。 http://localhost:6543/ . 正常开放 tutorial/views/default.pyviews 包。它应该已经包含以下内容:

1from pyramid.view import view_config
2
3from ..models import MyModel
4
5
6@view_config(context=MyModel, renderer='tutorial:templates/mytemplate.pt')
7def my_view(request):
8    return {'project': 'myproj'}

让我们试着理解本模块中的组件:

  1. Lines 1-3 . 执行一些依赖项导入。

  2. 第6行 . 使用 pyramid.view.view_config() configuration decoration 表演 view configuration 注册。此视图配置注册将在应用程序启动时激活。在我们的应用程序中记住 __init__.py 当我们执行 pyramid.config.Configurator.scan() 方法 config.scan() ?通过调用scan方法,Pyramid的配置程序将找到并处理这个 @view_config 并在应用程序中创建视图配置。未经处理 scan 装饰师实际上什么也不做。 @view_config 是惰性的,没有通过 scan .

    这个 @view_config decorator接受许多关键字参数。我们在这里使用两个关键字参数: contextrenderer .

    这个 context argument signifies that the decorated view callable my_view should only be run when traversal finds the tutorial.models.MyModel resource as the context of a request. In English this means that when the URL / is visited, and because `` mymodel``是根模型,将调用此视图可调用。

    这个 renderer 参数名为 asset specification 属于 tutorial:templates/mytemplate.pt . 此资产规格指向 Chameleon 存在于 mytemplate.pt 文件内 templates 目录 tutorial 包裹。事实上,如果你在 templates 这个包的目录,您将看到 mytemplate.pt 模板文件此模板呈现生成的项目的默认主页。此资产规格是 绝对的views 包裹。或者,我们可以使用相对资产规范 ../templates/mytemplate.pt .

    从这个电话到 @view_config 不通过 name 论点 my_view 它所修饰的函数表示当上下文为类型时可调用的“默认”视图 MyModel .

  3. Lines 7-8 . 一 view callable 已命名 my_view 定义,在上面的步骤中对其进行了修饰。此视图可调用为 功能 由CookiCutter生成。只有一个论点, request . 这是Pyramid的标准呼叫签名 view callable . 函数返回字典 {{'project': 'myproj'}} . 此词典由 mytemplate.pt 资产说明,用于在页面上填写某些值。

让我们打开 tutorial/views/notfound.pyviews 包以查看第二个视图。

1from pyramid.view import notfound_view_config
2
3
4@notfound_view_config(renderer='tutorial:templates/404.pt')
5def notfound_view(request):
6    request.response.status = 404
7    return {}

不必重复,我们将指出这一观点与前一观点之间的差异。

  1. 第4行 . 这个 notfound_view 功能装饰有 @notfound_view_config . 此装饰器注册 Not Found View 使用 pyramid.config.Configurator.add_notfound_view() .

    这个 renderer 参数名为 asset specification 属于 tutorial:templates/404.pt .

  2. Lines 5-7 . 一 view callable 已命名 notfound_view 定义,在上面的步骤中对其进行了修饰。它将HTTP响应状态代码设置为 404 . 函数将空字典返回给模板 404.pt ,它不接受任何参数。

配置 development.ini

这个 development.ini (在 tutorial project 目录,而不是 tutorial package 目录)如下所示:

###
# app configuration
# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
###

[app:main]
use = egg:tutorial

pyramid.reload_templates = true
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_debugtoolbar

zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000

retry.attempts = 3

# By default, the toolbar only appears for clients from IP addresses
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1

[pshell]
setup = tutorial.pshell.setup

###
# wsgi server configuration
###

[server:main]
use = egg:waitress#main
listen = localhost:6543

###
# logging configuration
# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
###

[loggers]
keys = root, tutorial

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = INFO
handlers = console

[logger_tutorial]
level = DEBUG
handlers =
qualname = tutorial

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s

注意是否存在 [app:main] 指定wsgi应用程序的部分。我们的zodb数据库设置被指定为 zodbconn.uri 在本节中设置。当服务器通过 pserve ,此节中的值作为 **settingsmain function defined in __init__.py .

测验

项目包含一个测试套件的基本结构,使用 pytest . 稍后将介绍结构 添加测试 .