无法添加我的基于原型的内容类型

My Archetypes-based content type can't be added

我正在开发一个附加包,它引入了一些基于原型的内容类型; 这些在该包的默认配置文件中定义。

在快速安装程序中(重新)安装我的包后,我可以在类型工具中看到我的类型;但我无法将它们添加到 TTW,并且它们未在 folder_constraintypes_form 中列出。我在文件夹门户类型的 "Allowed content types" 多 select 列表中做了 select 它们。

由于我在 bin/instance debug 会话中从 FactoryTypeInformation._getFactoryMethod 获得了 ValueError,我 "developed" Products.CMFPlone(分支 2.2)并更改了TypesTool.py 像这样:

from pprint import pprint                 # ADDED
...
class FactoryTypeInformation(TypeInformation):
    ...
    def _getFactoryMethod(self, container, check_security=1):
        if not self.product or not self.factory:
            raise ValueError, ('Product factory for %s was undefined' %
                               self.getId())
        pd = container.manage_addProduct  # ADDED
        p = container.manage_addProduct[self.product]
        self_product = self.product       # ADDED
        self_factory = self.factory       # ADDED
        m = getattr(p, self.factory, None)
        if m is None:
            pprint(locals())              # ADDED
            raise ValueError, ('Product factory for %s was invalid' %
                               self.getId())
        if not check_security:
            return m
        if getSecurityManager().validate(p, p, self.factory, m):
            return m
        raise AccessControl_Unauthorized( 'Cannot create %s' % self.getId() )

debug 会话现在看起来像这样:

>>> root = app.plone
>>> from Products.CMFCore.utils import getToolByName
>>> tmp_folder = root.temp
>>> type_name = 'MyType'
>>> types_tool = getToolByName(tmp_folder, 'portal_types')
>>> type_info = types_tool.getTypeInfo(type_name)
>>> type_info
<DynamicViewTypeInformation at /plone/portal_types/MyType>
>>> new_content_item = type_info._constructInstance(tmp_folder, 'shiny_new_object')
{'check_security': 0,
 'container': <ATFolder at /plone/temp>,
 'pd': <App.FactoryDispatcher.ProductDispatcher object at 0x227afd0>,
 'p': <App.FactoryDispatcher.FactoryDispatcher object at 0x7b97450>,
 'self': <DynamicViewTypeInformation at /plone/portal_types/MyType>,
 'm': None,
 'self_factory': 'addMyType',
 'self_product': 'MyCompany.MyProduct'}
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/zope/instances/zope-devel/src/Products.CMFCore/Products/CMFCore/TypesTool.py", line 551, in _constructInstance
    m = self._getFactoryMethod(container, check_security=0)
  File "/opt/zope/instances/zope-devel/src/Products.CMFCore/Products/CMFCore/TypesTool.py", line 467, in _getFactoryMethod
    self.getId())
ValueError: Product factory for MyType was invalid

因此,FactoryDispatcher 缺少必要的 addMyType 属性。 可能是我的声明不完整?

这是我的:

config.py:

# -*- coding: utf-8 -*-
from Products.CMFCore.permissions import setDefaultRoles
from os import sep

from .permissions import (AddMyType,
        )

PROJECTNAME = "MyCompany.MyProduct"
PRODUCT_HOME = sep.join(__file__.split(sep)[:-1])

MANAGERS_ONLY = ('Manager',)
MANAGERS_AND_OWNER = ('Manager', 'Owner')

# Permissions
DEFAULT_ADD_CONTENT_PERMISSION = "Add portal content"
setDefaultRoles(DEFAULT_ADD_CONTENT_PERMISSION, MANAGERS_AND_OWNER)
ADD_CONTENT_PERMISSIONS = {
    'MyType': AddMyType,
}
for perm in ADD_CONTENT_PERMISSIONS.values():
    setDefaultRoles(perm, MANAGERS_ONLY)

content/mytype.py:

# -*- coding: utf-8 -*-
__author__ = """unknown <unknown>"""
__docformat__ = 'plaintext'

from AccessControl import ClassSecurityInfo
from zope.interface import implements
from ..interfaces import IMyType

from ..config import PROJECTNAME

from Products.ATContentTypes.content.base import ATCTContent
from Products.ATContentTypes.content.schemata import ATContentTypeSchema
from Products.ATContentTypes.content.base import registerATCT as registerType

MyType_schema = (
    ATContentTypeSchema.copy()
    )

class MyType(ATCTContent):
    """
    description of my type
    """
    security = ClassSecurityInfo()
    implements(IMyType)
    meta_type = 'MyType'
    _at_rename_after_creation = True

    schema = MyType_schema

registerType(MyType, PROJECTNAME)

interfaces.py:

# -*- coding: utf-8 -*-
"""Module where all interfaces, events and exceptions live."""

from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from zope.interface import Interface

class ISupBetonqualiLayer(IDefaultBrowserLayer):
    """Marker interface that defines a browser layer."""

class IMyType(Interface):
    """Marker interface for .mytype.MyType
    """

permissions.py:

# -*- coding: utf-8 -*- vim: ts=8 sts=4 sw=4 si et tw=79
"""
Permissions
"""
AddMyType = 'MyCompany.MyProduct: Add MyType'

profiles/default/factorytool.xml:

<?xml version="1.0"?>
<object name="portal_factory" meta_type="Plone Factory Tool">
 <factorytypes>
  <type portal_type="MyType"/>
 </factorytypes>
</object>

profiles/default/rolemap.xml:

<?xml version="1.0"?>
<rolemap>
  <roles>
    <role name="MyAuthor"/>
  </roles>
  <permissions>
    <permission name="MyCompany.MyProduct: Add MyType" acquire="True">
      <role name="MyAuthor"/>
      <role name="Manager"/>
    </permission>
  </permissions>
</rolemap>

profiles/default/types.xml:

<?xml version="1.0"?>
<object name="portal_types"
        meta_type="Plone Types Tool">
 <object name="MyType"
         meta_type="Factory-based Type Information with dynamic views"/>
</object>

profiles/default/types/MyType.xml:

<?xml version="1.0"?>
<object name="MyType"
        meta_type="Factory-based Type Information with dynamic views"
        xmlns:i18n="http://xml.zope.org/namespaces/i18n">
 <property name="title">MyType</property>
 <property name="description">
 Some description text which is indeed visible in the types tool
 </property>
 <property name="content_icon">SomeExisting.png</property>
 <property name="content_meta_type">MyType</property>
 <property name="product">MyCompany.MyProduct</property>
 <property name="factory">addMyType</property>
 <property name="immediate_view">mytype_view</property>
 <property name="global_allow">True</property>
 <property name="filter_content_types">False</property>
 <property name="allowed_content_types">
 </property>
 <property name="allow_discussion">False</property>
 <property name="default_view">mytype_view</property>
 <property name="view_methods">
  <element value="base_view"/>
 </property>
 <property name="default_view_fallback">False</property>
 <alias from="(Default)" to="(dynamic view)"/>
 <alias from="index.html" to="(dynamic view)"/>
 <alias from="view" to="(selected layout)"/>
 <alias from="edit" to="base_edit"/>
 <alias from="properties" to="base_metadata"/>
 <action title="View"
         action_id="view"
         category="object"
         condition_expr=""
         url_expr="string:${object_url}/view"
         visible="True">
  <permission value="View"/>
 </action>
 <action title="Edit"
         action_id="edit"
         category="object"
         condition_expr="not:object/@@plone_lock_info/is_locked_for_current_user"
         url_expr="string:${object_url}/edit"
         visible="True">
  <permission value="Modify portal content"/>
 </action>
</object>

在有人告诉我这样做之前:我已经创建了 a question in the Plone community forum;到目前为止没有运气。如果任一页面上有重要信息,我会同步它。

这些是使您的内容类型可添加的缺失部分:

1.) 通过添加以下内容在 MyCompany/MyProduct/configure.zcml 中注册内容目录:

<include package=".content" />

2.) 添加包含以下内容的文件 MyCompany/MyProduct/content/configure.zcml

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:five="http://namespaces.zope.org/five"
    i18n_domain="MyCompany.MyProduct">

  <class class=".mytype.MyType">
    <require
        permission="zope2.View"
        interface="..interfaces.IMyType"
        />
  </class>

</configure>

3.) 通过将 class MyType(*basecls) 替换为 class MyType(ATCTContent) 来修复 MyCompany/MyProduct/content/mytype.py 中随后发生的语法错误。

最后但并非最不重要的是,删除以前使事情正常进行的尝试。最好是将类型外包给专用的 pckg 并使用 zopeskel 创建它,imo。

对于添加类型后出现的视图错误,请随时打开新任务;-)