0

我基于 Plone Dexterity 定义了一些内容类型,我希望任何内容类型都有自己的 ID。所以我使用了 zope.schema.Id 。

class IArticle(form.Schema, IImageScaleTraversable):
    """
    Article
    """

    form.model("models/article.xml")

    id = schema.Id(
        title=_(u"Identifier"),
        description=_(u"The unique identifier of object."),
        required=False
    )

当我创建一个新的文章对象时,它工作正常,但是当我想修改现有文章的 Id 时,它总是显示错误:

 {'args': (<MultiContentTreeWidget 'form.widgets.IRelatedItems.relatedItems'>,),
 'context': <Article at /dev/articles/this-is-another-articles>,
 'default': <object object at 0x100266b20>,
 'loop': {},
 'nothing': None,
 'options': {},
 'repeat': {},
 'request': <HTTPRequest, URL=http://localhost:8083/dev/articles/this-is-another-article/@@edit>,
 'template': <zope.browserpage.viewpagetemplatefile.ViewPageTemplateFile object at 0x10588ecd0>,
 'view': <MultiContentTreeWidget 'form.widgets.IRelatedItems.relatedItems'>,
 'views': <zope.browserpage.viewpagetemplatefile.ViewMapper object at 0x10b309f50>}
 .......
 .......
 .......
Module zope.tales.expressions, line 217, in __call__
Module zope.tales.expressions, line 211, in _eval
Module plone.formwidget.contenttree.widget, line 147, in render_tree
Module plone.app.layout.navigation.navtree, line 186, in buildFolderTree
Module Products.CMFPlone.CatalogTool, line 427, in searchResults
Module Products.ZCatalog.ZCatalog, line 604, in searchResults
Module Products.ZCatalog.Catalog, line 907, in searchResults
Module Products.ZCatalog.Catalog, line 656, in search
Module Products.ZCatalog.Catalog, line 676, in sortResults
Module plone.app.folder.nogopip, line 104, in documentToKeyMap
Module plone.folder.ordered, line 102, in getObjectPosition
Module plone.folder.default, line 130, in getObjectPosition
ValueError: No object with id "this-is-another-articles" exists.
4

4 回答 4

2

我不认为这是库存编辑表单中支持的用例。您可以从包含项目的文件夹的文件夹内容选项卡重命名项目。如果您想从编辑表单中执行此操作:

  • 您可能需要使用自定义编辑表单(子类化现有表单);
  • 将您的 id 字段命名为“id”以外的名称,可能是“target_id”或“shortname”
  • 让表单的 __call__() 方法更新/保存表单,并且仅在成功时重命名其容器中的项目。
  • __call__() 应该在触发名称更改的编辑后重定向到新项目的 URL。

也许像(完全未经测试):

from plone.dexterity.browser.edit import DefaultEditForm as BaseForm
from Products.statusmessages.interfaces import IStatusMessages

class RenameEnabledEditForm(BaseForm):
    def __call__(self, *args, **kwargs):
         self.update(*args, **kwargs)
         data, errors = self.extractData()
         existing, newid = self.context.getId(), data.get('target_id')
         if not errors and existing != newid:
             parent_folder = self.context.__parent__
             if newid in parent_folder.objectIds():
                 raise RuntimeError('Duplicate object id')  # collision!
             parent_folder.manage_renameObject(existing, newid)
             newurl = parent_folder[newid].absolute_url()
             IStatusMessages(self.context).addStatusMessage(
                 u'Renamed item from "%s" to "%s" in folder' % (existing, newid),
                 type='info',
                 )
             self.request.response.redirect(newurl)
         else:
             return self.index(*args, **kwargs)
于 2012-04-09T21:05:42.730 回答
0

为了与灵巧的内容类型一起使用,我改编了@spdupton 的答案(更正导入中的错字)并将 self.context 更改为 self.request

from Products.statusmessages.interfaces import IStatusMessage

class EditForm(dexterity.EditForm):
    grok.context(IPics)


    def applyChanges(self, data):    
        existing = self.context.getId()
        data, errors = self.extractData()
        super(EditForm, self).applyChanges(data)


        newid = str(data.get('picName'))

        print 'existing, newid =', existing, newid
        if not errors and existing != newid:
            parent_folder = self.context.__parent__
            if newid in parent_folder.objectIds():
                raise RuntimeError('Duplicate object id')  # collision!
            parent_folder.manage_renameObject(existing, newid)
            newurl = parent_folder[newid].absolute_url()
            IStatusMessage(self.request).addStatusMessage(
                u'Renamed item from "%s" to "%s"' % (existing, newid),
                type='info',
                )
            self.request.response.redirect(newurl)

#

于 2015-01-27T21:31:40.710 回答
0

还有一个未解决的问题和初步工作,以使敏捷类型支持标准“在内容上显示'短名称'?”-功能。

于 2012-04-11T07:19:43.917 回答
0

我已经通过自定义添加表单实现了这一点,因此只有添加表单包含 id-field 而编辑表单不包含(重命名是通过重命名操作或从文件夹内容视图以旧方式完成的)。

一些样板:

from five import grok

from zope import schema

from plone.directives import form
from plone.directives import dexterity


class IMyContent(form.Schema):
    """Schema of MyContent"""


class NotValidId(schema.ValidationError):
    """Id is not valid."""


def isValidId(value):
    """Validates id for new MyContent objects"""
    # raise NotValidId(value)
    return True


class IMyContentAddForm(IMyContent):
    """Schema of MyContent Add Form"""

    form.order_before(id="*")
    id = schema.ASCIILine(
        title=u"Id",
        constraint=isValidId,
        required=True
        )


class MyContentAddForm(dexterity.AddForm):
    """Add Form for new MyContent objects"""
    grok.name("my.app.mycontent")

    label = u"Add New"
    schema = IMyContentAddForm

    def create(self, data):
        """Creates a new object with the given (validated) id"""
        id = data.pop("id")
        obj = super(MyContentAddForm, self).create(data)
        obj.id = id
        return obj
于 2012-04-11T07:14:56.370 回答