Python 在Plone中循环通过断开的对象
我有几个破碎的对象,我希望在python脚本中循环。我的用例如下:我已将自定义产品从Python 在Plone中循环通过断开的对象,python,plone,zope,zodb,Python,Plone,Zope,Zodb,我有几个破碎的对象,我希望在python脚本中循环。我的用例如下:我已将自定义产品从My.oldproduct重命名为My.newproduct。这导致以前使用my.oldproduct保存的对象被破坏,因此无法访问。有一个解决方法,如下所述: 现在我要做的是在ZMI中创建一个python脚本,循环遍历所有损坏的内容,更改/更新它们,从而使用my.newproduct保存它们 我无法获取旧对象,因为它们未列出。查看我的python脚本示例,列出站点中的所有内容,但它们仍然没有显示: from P
My.oldproduct
重命名为My.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
中获得要列出的损坏对象?恐怕您需要手动遍历整个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.breaked.breaked
对象执行上述操作没有什么意义
上述脚本充当bin/instance run
脚本,按如下方式运行:
bin/instance run path/to/this/script.py
您将要处理站点中的所有内容,这是一个相当繁重的过程,将涉及大量缓存搅动,并且可能涉及大量提交,其中可能存在冲突。您确实不想通过web脚本来运行它。恐怕您需要手动遍历整个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.breaked.breaked
对象执行上述操作没有什么意义
上述脚本充当bin/instance run
脚本,按如下方式运行:
bin/instance run path/to/this/script.py
您将要处理站点中的所有内容,这是一个相当繁重的过程,将涉及大量缓存搅动,并且可能涉及大量提交,其中可能存在冲突。您确实不想通过web脚本运行此代码。谢谢Martijn,但由于权限不足,我无法在ZMI中以python脚本的形式执行此代码。(受限Python)。考虑到这是一项一次性任务,我觉得将其添加到我的产品的文件系统以允许执行上述任务很奇怪。@Frankline:进一步充实它;你真的不想在网上运行它。可以(将
deque
替换为常规列表和.pop(0)
而不是.popleft()
,省去事务.commit()
和打印
语句),我只是觉得这不是一个好主意。谢谢Martijn,但由于权限不足,我无法在ZMI中以python脚本的形式执行此代码。(受限Python)。考虑到这是一项一次性任务,我觉得将其添加到我的产品的文件系统以允许执行上述任务很奇怪。@Frankline:进一步充实它;你真的不想在网上运行它。这是可能的(将deque
替换为常规列表和.pop(0)
而不是.popleft()
,省去事务.commit()
和print
语句),我认为这不是一个好主意。