跳转到主要内容

为PMR2定制z3c.form和plone.z3cform库

项目描述

介绍

此软件包扩展了z3c.form和plone.z3cform,以便在PMR2和相关库中使用。此软件包试图解决的问题包括

  • 确保在渲染表单(以及视图/页面)时采用正确的根模板,以便只有一个类用于测试和生产,无需为特定用途进行子类化或使用包装类/方法。可能可以通过将根视图注册到所需的层来支持其他框架。

  • 通过使用适当的表单验证器(例如,Plone的plone.protect)来预防CSRF(跨站请求伪造)。

  • 向标准非表单视图提供相同的可适应浏览器类(页面)。

  • 带有遍历子路径的表单。

安装和使用

只需在典型的setup.py中的设置函数中添加或修改install_requires选项。示例

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-01-11

  • 在单元测试环境中,直接使用视图应适用于plone.protect 2和3。

  • 确保这里的本地测试用例与Products.PloneHotfix20160830引入的修复兼容。

  • 更新keyring支持以处理匿名测试用户,以便遵循相同的逻辑。

0.3 - 2017-01-05

  • 支持由plone.protect>3和plone.keyring>3引入的表单特定keyring;也支持回退。

0.2.1 - 2013-10-24

  • 打包修复;这是为了措辞和更干净的通用设置集成。

0.2 - 2013-07-09

  • 现在提供定制的ploneform宏,这些宏已从pmr2.app模块迁移而来。

  • 使用Bootstrap类

  • 已移除过时的zope.app.*导入。

0.1 - 2013-01-17

  • pmr2库的各种辅助表单和视图类的初始发布。

  • 提供可以适应多个包装模板的包装BrowserView类,就像plone.z3cform所做的那样,以便视图不会调用可能由于缺少完整门户而不可用的项目。

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装软件包的信息。

源分发

pmr2.z3cform-0.3.3.tar.gz (24.5 kB 查看散列)

上传时间

由以下支持

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