为pmr2定制z3c.form和plone.z3cform库
pmr2.z3cform的Python项目详细描述
简介
这个包扩展了z3c.form和plone.z3cform,以便在pmr2中使用 以及相关的图书馆。此软件包试图解决的问题是:
- Ensure the correct root template is adapted when forms (and views/ pages) are rendered, such that there will only be one class used for testing and production, without having to subclass for specific uses or make use of wrapper classes/methods. It may be possible to support other frameworks by registering the root view to the desired layer.
- CSRF (Cross-Site Request Forgery) prevention via the use of appropriate form authenticators, e.g. plone.protect for Plone.
- Offer the same adaptable browser class (pages) to standard non-form views.
- Forms with traversal subpaths.
安装和使用
只需在设置中添加或修改install_requires选项 典型的setup.py中的函数。示例:
from setuptools import setup setup( ... install_requires=[ ... 'pmr2.z3cform', ] )
表格
PMR2中的表单是在z3c.forms的基础上构建的。有些变化 我们使这个库能够更好地适应我们的用例。在那里 是两个修改,第一个是请求的执行 方法,另一种是csrf(跨站点请求伪造)保护。
首先,我们导入一些基类并创建一个测试表单类:
>>> import zope.interface >>> import zope.schema >>> import z3c.form.field >>> from pmr2.z3cform.testing import BaseTestRequest as TestRequest >>> from pmr2.z3cform.tests import base >>> from pmr2.z3cform.form import AddForm >>> >>> class IDummy(zope.interface.Interface): ... id = zope.schema.DottedName(title=u'id') ... >>> class Dummy(object): ... zope.interface.implements(IDummy) ... def __init__(self, id_): ... self.id = id_ ... >>> class TestAddForm(AddForm): ... fields = z3c.form.field.Fields(IDummy) ... def create(self, data): ... return Dummy(data['id']) ... def add_data(self, ctxobject): ... ctxobject.id = self._data['id'] ... def add(self, obj): ... self.context.append(obj) ... def nextURL(self): ... return '' # unnecessary.
首先要演示的是请求方法验证。形式 操作数据不能由简单的get请求激活:
>>> context = [] >>> request = TestRequest(form={ ... 'form.widgets.id': 'test', ... 'form.buttons.add': '1', ... }) >>> request.method = 'GET' >>> form = TestAddForm(context, request) >>> result = form() Traceback (most recent call last): ... Unauthorized: Unauthorized() >>> context == [] True
另一方面,POST请求不会触发权限错误:
>>> request.method = 'POST' >>> form = TestAddForm(context, request) >>> form.disableAuthenticator = True >>> result = form() >>> print context[0].id test
但是,请注意,安全验证器已禁用。这是什么 提供对CSRF预防令牌的检查,该令牌必须是 请求。现在在启用检查的情况下尝试上述操作,因为它将通过 默认值:
>>> context = [] >>> request.method = 'POST' >>> form = TestAddForm(context, request) >>> result = form() Traceback (most recent call last): ... Unauthorized: Unauthorized() >>> context == [] True
如果提供了令牌,则作为常规表单提交过程的一部分 使用此网站呈现的表单,令牌将包含在 隐藏的输入字段。在plone的情况下,这个标记由 验证器视图。如果我们包含生成的令牌 将正确提交:
>>> context = [] >>> authed_request = base.TestRequest(form=request.form) >>> authed_request.method = 'POST' >>> '_authenticator' in authed_request.form True >>> form = TestAddForm(context, authed_request) >>> result = form() >>> print context[0].id test
页码
这些只是简单的呈现页面,用于通过布局包装 类将被更标准的plone呈现方式替换 模板。
让我们将一个子类:
>>> from pmr2.z3cform.tests.base import TestRequest >>> from pmr2.z3cform.page import SimplePage >>> >>> class TestPage(SimplePage): ... template = lambda x: 'Hello'
然后渲染:
>>> context = self.portal >>> request = TestRequest() >>> page = TestPage(context, request) >>> print page() <h1 class="documentFirstHeading">Plone site</h1> <div id="content-core"> <div>Hello</div> </div>
如果我们在主站点上注册这个视图,我们应该能够 使用testbrowser。这将呈现相同的页面 所有与plone相关的模板:
>>> import zope.component >>> from Testing.testbrowser import Browser >>> zope.component.provideAdapter(TestPage, (None, None), ... zope.publisher.interfaces.browser.IBrowserView, ... name='pmr2z3cform-testpage') ... >>> tb = Browser() >>> tb.open(context.absolute_url() + '/@@pmr2z3cform-testpage') >>> 'Plone - http://plone.org' in tb.contents True >>> '<div>Hello</div>' in tb.contents True
虽然遍历视图通常是特定于实现的,但是 示威仍然是可能的。尝试子类化一个:
>>> from pmr2.z3cform.page import TraversePage >>> >>> class TestTraversePage(TraversePage): ... _template = 'Subpath is: %s' ... def template(self): ... subpath = '/'.join(self.traverse_subpath) ... return self._template % subpath
手动模拟遍历并呈现表单:
>>> context = self.portal >>> request = TestRequest() >>> page = TestTraversePage(context, request) >>> p = page.publishTraverse(request, 'a') >>> p = page.publishTraverse(request, 'b') >>> print page() <h1 class="documentFirstHeading">Plone site</h1> <div id="content-core"> <div>Subpath is: a/b</div> </div>
很像simplepage示例,请重新注册:
>>> zope.component.provideAdapter(TestTraversePage, (None, None), ... zope.publisher.interfaces.browser.IBrowserView, ... name='pmr2z3cform-testtraversepage') ... >>> tb = Browser() >>> tb.open(context.absolute_url() + '/@@pmr2z3cform-testtraversepage' + ... '/a/b/c/some_path') >>> 'Plone - http://plone.org' in tb.contents True >>> '<div>Subpath is: a/b/c/some_path</div>' in tb.contents True
更改日志
0.3.3-2017年1月11日
- 直接使用视图应该对plone.protect 2和3都有效 在unittesting环境中。
- 确保这里的本地测试用例使用 产品.plonehotfix 20160830.
- 更新keyring支持以处理匿名测试用户以允许 遵循同样的逻辑。
0.3-2017-01-05
- 支持plone.protect引入的特定于窗体的键环>;3 和plone.keyring>;3;也支持回退。
0.2.1-2013年10月24日
- 打包修复;这是为措辞和更干净的通用设置而完成的 整合。
0.2-2013年7月9日
- 现在提供定制的ploneform宏,从 pmr2.app模块。
- 使用引导类
- 删除了不推荐使用的zope.app.*导入。
0.1-2013-01-17
- PMR2的各种帮助程序窗体和视图类的初始版本 图书馆。
- 提供一个包装好的browserview类,该类可以适应多个包装器 模板很像plone.z3cform,这样视图就不会调用 由于缺少完整门户而可能不可用的项。