1

我有几个损坏的对象,我希望在 python 脚本中循环。我的用例如下:我已将我的自定义产品从 重命名my.oldproductmy.newproduct。这导致先前保存的对象my.oldproduct被破坏,因此无法访问。这里有一个详细的解决方法:更新损坏的对象

现在我想做的是在 ZMI 中创建一个 python 脚本来循环所有损坏的内容,更改/更新它们,从而使用 my.newproduct 保存它们。

我一直无法获取旧对象,因为它们未列出。查看我的 python 脚本示例以列出站点中的所有内容,但它们仍然没有显示:

from Products.CMFCore.utils import getToolByName

app = context.restrictedTraverse('/')
sm = app.plone.getSiteManager()

catalog = getToolByName(context, 'portal_catalog')
results = catalog.searchResults()

count = 0
for obj in results:
    print obj.meta_type
    count += 1

print str("Found " + str(count) + " matching objects")

return printed

我怎样才能让破碎的物体my.oldproduct被列出来?

4

1 回答 1

4

恐怕您需要手动遍历整个 ZODB。如果这些对象是内容对象,您应该能够使用标准的 OFS 方法:

from collections import deque
from datetime import datetime

import transaction
from zope.app.component.hooks import setSite
from Testing.makerequest import makerequest
from AccessControl.SecurityManagement import newSecurityManager

from my.newproduct.types import ArchetypesContentType


site_id = 'Plone'     # adjust to match your Plone site object id.
admin_user = 'admin'  # usually 'admin', probably won't need adjusting
app = makerequest(app)
site = app[site_id]
setSite(site)
user = app.acl_users.getUser(admin_user).__of__(site.acl_users)
newSecurityManager(None, user)


def treeWalker(root):
    # stack holds (parent, id, obj) tuples
    stack = deque([(None, None, root)])
    while stack:
        parent, id, next = stack.popleft()
        try:
            stack.extend((next, id, child) for id, child in next.objectItems())
        except AttributeError:
            # No objectItems method
            pass
        yield parent, id, next


count = 0
for parent, id, obj in treeWalker(site):
    if isinstance(obj, ArchetypesContentType):
        print 'Found content type object {} at {}'.format(id, '/'.join(object.getPhysicalPath()))
        obj._p_changed = True  # mark it as changed, force a commit
        count += 1
        if count % 100 == 0:
            # flush changes so far to disk to minimize memory usage
            transaction.savepoint(True)
            print '{} - Processed {} items'.format(datetime.now(), count)

transaction.commit()

这假设您已经包含了您链接到的解决方法;尝试对ZODB.broken.Broken对象进行上述操作没有什么意义。

上面的脚本作为一个bin/instance run脚本,这样运行它:

bin/instance run path/to/this/script.py

您将处理站点中的所有内容,这是一个相当繁重的过程,将涉及大量缓存流失,并且可能涉及具有潜在冲突的大量提交。您真的不想将其作为通过网络脚本运行。

于 2013-04-11T15:12:00.617 回答