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/pl开发者_开发百科one-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?
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.
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.
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
精彩评论