基本布局¶
由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 . 这个
MyModelresource 类在此处实现。此类的实例能够在 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_configdecorator接受许多关键字参数。我们在这里使用两个关键字参数:context和renderer.这个
contextargument signifies that the decorated view callablemy_viewshould only be run when traversal finds thetutorial.models.MyModelresource 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 . 稍后将介绍结构 添加测试 .