我在Plone 4.2.5中使用plone.directives.form版本1.0,升级到4.2.6后,我开始看到以下追溯,并且由于plone.directives.form
而我猜测升级到1.1版。
如何避免此错误?唯一不是来自追踪中默认Plone的代码行位于der.freitag.handlers
,其中transaction.commit()
执行1385740390.020.496977141203 http://10.100.0.207:8081/website/front-page/atomkraft/++add++der.freitag.customizablearticlelink
Traceback (innermost last):
Module ZPublisher.Publish, line 138, in publish
Module ZPublisher.mapply, line 77, in mapply
Module ZPublisher.Publish, line 48, in call_object
Module plone.z3cform.layout, line 70, in __call__
Module plone.z3cform.layout, line 54, in update
Module plone.dexterity.browser.add, line 112, in update
Module plone.z3cform.fieldsets.extensible, line 59, in update
Module plone.z3cform.patch, line 30, in GroupForm_update
Module z3c.form.group, line 138, in update
Module z3c.form.action, line 99, in execute
Module z3c.form.button, line 315, in __call__
Module z3c.form.button, line 170, in __call__
Module plone.dexterity.browser.add, line 99, in handleAdd
Module z3c.form.form, line 247, in createAndAdd
Module plone.dexterity.browser.add, line 78, in add
Module plone.dexterity.utils, line 152, in addContentToContainer
Module Products.BTreeFolder2.BTreeFolder2, line 455, in _setObject
Module zope.event, line 31, in notify
Module zope.component.event, line 24, in dispatch
Module zope.component._api, line 136, in subscribers
Module zope.component.registry, line 321, in subscribers
Module zope.interface.adapter, line 585, in subscribers
Module zope.component.event, line 32, in objectEventNotify
Module zope.component._api, line 136, in subscribers
Module zope.component.registry, line 321, in subscribers
Module zope.interface.adapter, line 585, in subscribers
Module der.freitag.handlers, line 126, in set_customizable_article_link_id
Module transaction._manager, line 89, in commit
Module transaction._transaction, line 329, in commit
Module transaction._transaction, line 443, in _commitResources
Module ZODB.Connection, line 567, in commit
Module ZODB.Connection, line 623, in _commit
Module ZODB.Connection, line 658, in _store_objects
Module ZODB.serialize, line 422, in serialize
Module ZODB.serialize, line 431, in _dump
PicklingError: Can't pickle <class 'plone.directives.form.schema.Schema'>: attribute lookup plone.directives.form.schema.Schema failed
,内容类型只是常规的灵活内容类型。
z3c.relationfield.schema.RelationChoice
编辑:正在创建的对象有一个关系字段(zc.relation
),事实证明{{1}}保留了每个成员提供的所有接口的列表任何关系。因此,在从plone.directives.form版本1.0升级到版本1.1之后,无法再解析plone.directives.form上的接口。
从z3c.relationfield文档中我看不到更新关系的任何选项,因此唯一的解决方案是获取所有关系并重新创建它们吗?
答案 0 :(得分:3)
仅供参考,我是如何解决的:
仍然在plone.directives.form
1.0上更新您的对象,以便它们不再提供plone.directives.form.schema.Schema
界面。
然后重新创建关系:
from z3c.relationfield import RelationValue
from zc.relation.interfaces import ICatalog
from zope.app.intid.interfaces import IIntIds
from zope.component import getUtility
from zope.event import notify
from zope.lifecycleevent import ObjectModifiedEvent
logger = logging.getLogger(LOGGER)
relations_catalog = getUtility(ICatalog)
intids = getUtility(IIntIds)
relations = [rel for rel in relations_catalog.findRelations()]
len_relations = len(relations)
logger.info('Relations needed to update: {0}'.format(len_relations))
for relation in relations:
# get the object link and the object linked
object_with_link = relation.from_object
object_linked_to = relation.to_object
# remove the broken relation
object_with_link.reference = None
# let the catalog remove the old relation
notify(ObjectModifiedEvent(object_with_link))
# create a new relation
object_linked_to_intid = intids.getId(object_linked_to)
new_relation = RelationValue(object_linked_to_intid)
object_with_link.reference = new_relation
# let the catalog know about this new relation
notify(ObjectModifiedEvent(object_with_link))
在此之后,停止实例,再次运行buildout以将plone.directives.form
更新为1.1版和voilà!
答案 1 :(得分:1)
Schema类现在位于plone.supermodel.model中,而不是plone.directives.form.schema。
但是,您应该尝试修复的实际问题是代码是出于某种原因试图在ZODB中存储架构。不支持酸洗/去除Zope接口。
答案 2 :(得分:0)
如果有人遇到这种类型的问题并且无法将旧包裹带回来,这是另一种方法:
import transaction
from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.User import system
from Testing.makerequest import makerequest
from zope.component.hooks import setSite
from zope.globalrequest import setRequest
from zc.relation.interfaces import ICatalog
from z3c.relationfield.event import _relations
from z3c.relationfield.event import _setRelation
from zope.component import getUtility
app = makerequest(app)
newSecurityManager(None, system)
portal = app.Plone
setSite(portal)
portal.REQUEST['PARENTS'] = [portal]
portal.REQUEST.setVirtualRoot('/')
setRequest(portal.REQUEST)
THRESHOLD = 100
relations_catalog = getUtility(ICatalog)
paths = ['/'.join(r.from_object.getPhysicalPath())
for r in relations_catalog.findRelations() if r.from_object]
relations_catalog.clear()
counter = 0
for path in paths:
obj = app.unrestrictedTraverse(path)
for name, relation in _relations(obj):
_setRelation(obj, name, relation)
counter += 1
if counter % THRESHOLD == 0:
transaction.savepoint()
transaction.commit()
答案 3 :(得分:0)
还有一个选项,我开发了一个名为collective.diversion的软件包,旨在减轻移动类时酸洗错误的痛苦。上述任何一个脚本都不适合我,但是使用collective.diversion。
将包添加到buildout并包含以下ZCML会导致加载项目,并且它们将在写入时保留在正确的位置,因此重新编制目录索引就足够了。
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:diversion="http://namespaces.plone.org/diversion">
<diversion:class
old="plone.directives.form.schema.Schema"
new="plone.supermodel.model.Schema"
/>
</configure>