基本布局¶
由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_templates
, zodbconn.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']
Lines 4-5 . 这个
MyModel
resource 类在此处实现。此类的实例能够在 ZODB 因为类继承自persistent.mapping.PersistentMapping
类。这个__parent__
和__name__
是 traversal 协议。默认情况下,这些设置为None
表示这是 root 对象。Lines 8-12 .
appmaker
用于返回 应用程序根 对象。它被召唤 每一个要求 到 Pyramid 凭借root_factory
定义在我们的__init__.py
. 它还执行引导 创建 一个应用程序根目录(在zodb根目录对象中),如果该根目录不存在。引导是通过首先查看数据库是否具有持久的应用程序根来完成的。如果没有,那么我们创建一个实例,存储它,并提交事务。
然后返回应用程序根对象。
通过查看声明 views
包¶
我们的cookiecutter生成了一个默认值 views
代表我们打包。它包含两个视图。
第一个视图用于呈现访问URL时显示的页面。 http://localhost:6543/
. 正常开放 tutorial/views/default.py
在 views
包。它应该已经包含以下内容:
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'}
让我们试着理解本模块中的组件:
Lines 1-3 . 执行一些依赖项导入。
第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接受许多关键字参数。我们在这里使用两个关键字参数:context
和renderer
.这个
context
argument signifies that the decorated view callablemy_view
should only be run when traversal finds thetutorial.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
.Lines 7-8 . 一 view callable 已命名
my_view
定义,在上面的步骤中对其进行了修饰。此视图可调用为 功能 由CookiCutter生成。只有一个论点,request
. 这是Pyramid的标准呼叫签名 view callable . 函数返回字典{{'project': 'myproj'}}
. 此词典由mytemplate.pt
资产说明,用于在页面上填写某些值。
让我们打开 tutorial/views/notfound.py
在 views
包以查看第二个视图。
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 {}
不必重复,我们将指出这一观点与前一观点之间的差异。
第4行 . 这个
notfound_view
功能装饰有@notfound_view_config
. 此装饰器注册 Not Found View 使用pyramid.config.Configurator.add_notfound_view()
.这个
renderer
参数名为 asset specification 属于tutorial:templates/404.pt
.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
,此节中的值作为 **settings
到 main
function defined in __init__.py
.
测验¶
项目包含一个测试套件的基本结构,使用 pytest
. 稍后将介绍结构 添加测试 .