Plone 4 中的自定义编辑视图

发布于 2024-11-05 11:46:07 字数 3757 浏览 0 评论 0 原文

我创建了自定义内容类型(简历),并且希望提供自定义“编辑”视图。我的用例非常简单,我只想在编辑表单之前显示一个 HTML“免责声明”框。

首先,我将:复制

Products/ATContentTypes/skins/ATContentTypes/atct_edit.cpt
Products/ATContentTypes/skins/ATContentTypes/atct_edit.cpt.metadata

my/product/browser/ 中,

my/product/browser/resumeedit.cpt
my/product/browser/resumeedit.cpt.metadata

然后我在 my/product/browser/configure.zcml 中定义了一个新的 browser:page 节:

  <browser:page
   for="..interfaces.IResume"
   name="resume_edit"
   class=".resumeview.ResumeEdit"
   template="resumeedit.cpt"
   permission="cmf.ModifyPortalContent"
   />

my/product/browser/resumeview.py 中的简历类很简单:

class ResumeEdit(BrowserView):
""" A customization of the Resume Edit form
"""
    __call__  = ViewPageTemplateFile('resumeedit.cpt')

最后,我更改了 my/product/profiles/default/types/Resume 中“edit”的默认别名.xml

  <alias from="edit" to="resume_edit" />

安装后,添加或编辑简历内容类型会引发此异常:

Unauthorized: The container has no security assertions.  Access to 'id' of (Products.Five.browser.pagetemplatefile.ViewPageTemplateFile object at 0x1e8b7a50) denied.

通过提供 edit_macros.pt 的修补版本可以缓解此问题:

85c85
<             tal:attributes="action python:context.absolute_url()+'/'+template.id;
---
>             tal:attributes="action python:context.absolute_url()+'/'+path('template/getId|nothing');
203c203
<                    tal:attributes="value python:(last_referer and '%s/%s' % (context.absolute_url(), template.id) not in last_referer) and last_referer or (context.getParentNode() and context.getParentNode().absolute_url())"
---
>                    tal:attributes="value python:(last_referer and '%s/%s' % (context.absolute_url(), path('template/getId|nothing')) not in last_referer) and last_referer or (context.getParentNode() and context.getParentNode().absolute_url())"

不过,这会引发以下异常(' id-64121786'是我的简历项目的id):

  Module zope.tales.tales, line 696, in evaluate
   - URL: file:/home/zope/env26/plone-devel/eggs/Products.Archetypes-1.6.5-py2.6.egg/Products/Archetypes/skins/archetypes/widgets/field.pt
   - Line 63, Column 4
   - Expression: <PythonExpr errors.get(fieldName)>
   - Names:
      {'args': (),
       'container': <Resume at /cms/id-64121786>,
       'context': <Resume at /cms/id-64121786>,
       'default': <object object at 0x8e094c0>,
       'here': <Resume at /cms/id-64121786>,
       'loop': {},
       'nothing': None,
       'options': {},
       'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0x126e7470>,
       'request': <HTTPRequest, URL=http://localhost:8081/cms/id-64121786/resume_edit>,
       'root': <Application at >,
       'template': <Products.Five.browser.pagetemplatefile.ViewPageTemplateFile object at 0x117da910>,
       'traverse_subpath': [],
       'user': <PloneUser 'admin'>,
       'view': <Products.Five.metaclass.SimpleViewClass from /home/zope/env26/plone-devel/src/my.product/my/product/browser/resumeedit.cpt object at 0x126d8c90>,
       'views': <Products.Five.browser.pagetemplatefile.ViewMapper object at 0x126d8fd0>}
  Module Products.PageTemplates.ZRPythonExpr, line 49, in __call__
   - __traceback_info__: errors.get(fieldName)
  Module PythonExpr, line 1, in <expression>
  Module AccessControl.ImplPython, line 688, in guarded_getattr
AttributeError: 'NoneType' object has no attribute 'get'

我如何解决这个问题并为我的内容类型的编辑视图提供我自己的自定义模板?

I have created a custom content-type (Resume) and I wish to provide a custom 'edit' view. My use-case is very simple, I simply want to show an HTML "disclaimer" box before the edit form.

First of all I have copied:

Products/ATContentTypes/skins/ATContentTypes/atct_edit.cpt
Products/ATContentTypes/skins/ATContentTypes/atct_edit.cpt.metadata

into my/product/browser/ as

my/product/browser/resumeedit.cpt
my/product/browser/resumeedit.cpt.metadata

Then I have defined a new browser:page stanza in my/product/browser/configure.zcml:

  <browser:page
   for="..interfaces.IResume"
   name="resume_edit"
   class=".resumeview.ResumeEdit"
   template="resumeedit.cpt"
   permission="cmf.ModifyPortalContent"
   />

The resume class in my/product/browser/resumeview.py is simply:

class ResumeEdit(BrowserView):
""" A customization of the Resume Edit form
"""
    __call__  = ViewPageTemplateFile('resumeedit.cpt')

Finally, I have changed the default alias for 'edit' in my/product/profiles/default/types/Resume.xml:

  <alias from="edit" to="resume_edit" />

When installed, adding or editing a Resume content type throws this exception:

Unauthorized: The container has no security assertions.  Access to 'id' of (Products.Five.browser.pagetemplatefile.ViewPageTemplateFile object at 0x1e8b7a50) denied.

This is mitigated by providing a patched version of edit_macros.pt:

85c85
<             tal:attributes="action python:context.absolute_url()+'/'+template.id;
---
>             tal:attributes="action python:context.absolute_url()+'/'+path('template/getId|nothing');
203c203
<                    tal:attributes="value python:(last_referer and '%s/%s' % (context.absolute_url(), template.id) not in last_referer) and last_referer or (context.getParentNode() and context.getParentNode().absolute_url())"
---
>                    tal:attributes="value python:(last_referer and '%s/%s' % (context.absolute_url(), path('template/getId|nothing')) not in last_referer) and last_referer or (context.getParentNode() and context.getParentNode().absolute_url())"

Still, this raises the following exception ('id-64121786' is the id of my resume item) :

  Module zope.tales.tales, line 696, in evaluate
   - URL: file:/home/zope/env26/plone-devel/eggs/Products.Archetypes-1.6.5-py2.6.egg/Products/Archetypes/skins/archetypes/widgets/field.pt
   - Line 63, Column 4
   - Expression: <PythonExpr errors.get(fieldName)>
   - Names:
      {'args': (),
       'container': <Resume at /cms/id-64121786>,
       'context': <Resume at /cms/id-64121786>,
       'default': <object object at 0x8e094c0>,
       'here': <Resume at /cms/id-64121786>,
       'loop': {},
       'nothing': None,
       'options': {},
       'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0x126e7470>,
       'request': <HTTPRequest, URL=http://localhost:8081/cms/id-64121786/resume_edit>,
       'root': <Application at >,
       'template': <Products.Five.browser.pagetemplatefile.ViewPageTemplateFile object at 0x117da910>,
       'traverse_subpath': [],
       'user': <PloneUser 'admin'>,
       'view': <Products.Five.metaclass.SimpleViewClass from /home/zope/env26/plone-devel/src/my.product/my/product/browser/resumeedit.cpt object at 0x126d8c90>,
       'views': <Products.Five.browser.pagetemplatefile.ViewMapper object at 0x126d8fd0>}
  Module Products.PageTemplates.ZRPythonExpr, line 49, in __call__
   - __traceback_info__: errors.get(fieldName)
  Module PythonExpr, line 1, in <expression>
  Module AccessControl.ImplPython, line 688, in guarded_getattr
AttributeError: 'NoneType' object has no attribute 'get'

How can I solve this problem and provide my own customized template for the edit-view of my content-type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云淡月浅 2024-11-12 11:46:07

我建议不要复制 atct_edit.cpt。您真正需要做的就是配置一个编辑模板(看起来您知道如何做),然后覆盖适当的部分。请参阅文档 此处了解更多信息。

另外,我会首先从一个完全空白的编辑模板开始。然后在其中放入一些有效的 XHTML,例如 Hello world!并确保您可以通过单击编辑按钮加载编辑模板。

I would suggest not copying atct_edit.cpt. All you really need to do is configure an edit template (which it looks like you know how to do) then override the appropriate parts. See documentation here for more information.

Also, I would start with a completely blank edit template first. Then put some valid XHTML in it e.g. <span>Hello world!</span> and make sure you can load the edit template by clicking on the edit button.

薯片软お妹 2024-11-12 11:46:07

跟进亚历克斯的回答:如果您不反对额外的依赖项,另一种解决方案也可以通过 z3c.form/plone.autoform 提供您自己的编辑表单。请参阅本手册了解基本介绍/想法。

To follow up on alex's answer: an alternative solution could also be providing your own edit form via z3c.form/plone.autoform if you don't object against the extra dependencies. See this manual for the basic introduction/idea.

杀お生予夺 2024-11-12 11:46:07

您必须使用视图来实现此目的。

为每个视图注册一个视图,对渲染调用进行一些检查以显示您想要的内容。

所以你不必重新创建表单

You must use a viewlet to achieve this.

Register a viewlet for every views, make some check on rendering call display what every you want.

So you don't have to recreate the form

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文