创建一个 portal_user_catalog 并使用它(克隆)
Create a portal_user_catalog and have it used (Plone)
我正在为我的 Plone 站点创建一个分支(已经很长时间没有分支了)。该站点有一个用于用户配置文件的特殊目录对象(一种特殊的基于原型的对象类型),称为 portal_user_catalog
:
$ bin/instance debug
>>> portal = app.Plone
>>> print [d for d in portal.objectMap() if d['meta_type'] == 'Plone Catalog Tool']
[{'meta_type': 'Plone Catalog Tool', 'id': 'portal_catalog'},
{'meta_type': 'Plone Catalog Tool', 'id': 'portal_user_catalog'}]
这看起来很合理,因为用户配置文件没有 "normal" 对象的大部分索引,但有一小部分自己的索引。
因为我找不到如何从头开始创建这个对象的方法,所以我将它从旧站点(如 portal_user_catalog.zexp
)导出并导入到新站点。这似乎可行,但我无法将对象添加到导入的目录中,甚至无法显式调用 catalog_object
方法。相反,用户配置文件被添加到标准 portal_catalog
.
现在我在我的产品中发现了一个模块,似乎可以达到目的 (Products/myproduct/exportimport/catalog.py
):
"""Catalog tool setup handlers.
$Id: catalog.py 77004 2007-06-24 08:57:54Z yuppie $
"""
from Products.GenericSetup.utils import exportObjects
from Products.GenericSetup.utils import importObjects
from Products.CMFCore.utils import getToolByName
from zope.component import queryMultiAdapter
from Products.GenericSetup.interfaces import IBody
def importCatalogTool(context):
"""Import catalog tool.
"""
site = context.getSite()
obj = getToolByName(site, 'portal_user_catalog')
parent_path=''
if obj and not obj():
importer = queryMultiAdapter((obj, context), IBody)
path = '%s%s' % (parent_path, obj.getId().replace(' ', '_'))
__traceback_info__ = path
print [importer]
if importer:
print importer.name
if importer.name:
path = '%s%s' % (parent_path, 'usercatalog')
print path
filename = '%s%s' % (path, importer.suffix)
print filename
body = context.readDataFile(filename)
if body is not None:
importer.filename = filename # for error reporting
importer.body = body
if getattr(obj, 'objectValues', False):
for sub in obj.objectValues():
importObjects(sub, path+'/', context)
def exportCatalogTool(context):
"""Export catalog tool.
"""
site = context.getSite()
obj = getToolByName(site, 'portal_user_catalog', None)
if tool is None:
logger = context.getLogger('catalog')
logger.info('Nothing to export.')
return
parent_path=''
exporter = queryMultiAdapter((obj, context), IBody)
path = '%s%s' % (parent_path, obj.getId().replace(' ', '_'))
if exporter:
if exporter.name:
path = '%s%s' % (parent_path, 'usercatalog')
filename = '%s%s' % (path, exporter.suffix)
body = exporter.body
if body is not None:
context.writeDataFile(filename, body, exporter.mime_type)
if getattr(obj, 'objectValues', False):
for sub in obj.objectValues():
exportObjects(sub, path+'/', context)
我尝试使用它,但我不知道它应该如何完成;
我不能称之为 TTW(我应该尝试发布方法吗?!)。
我在 debug
会话中尝试过:
$ bin/instance debug
>>> portal = app.Plone
>>> from Products.myproduct.exportimport.catalog import exportCatalogTool
>>> exportCatalogTool(portal)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File ".../Products/myproduct/exportimport/catalog.py", line 58, in exportCatalogTool
site = context.getSite()
AttributeError: getSite
所以,如果这是要走的路,看来我需要一个 "real" 上下文。
更新: 为了获得这个上下文,我尝试了 External Method
:
# -*- coding: utf-8 -*-
from Products.myproduct.exportimport.catalog import exportCatalogTool
from pdb import set_trace
def p(dt, dd):
print '%-16s%s' % (dt+':', dd)
def main(self):
"""
Export the portal_user_catalog
"""
g = globals()
print '#' * 79
for a in ('__package__', '__module__'):
if a in g:
p(a, g[a])
p('self', self)
set_trace()
exportCatalogTool(self)
然而,当我调用它时,我得到了与 main
函数的参数相同的 <PloneSite at /Plone>
对象,它没有 getSite
属性。也许我的站点没有正确调用此类外部方法?
或者我是否需要在 configure.zcml
中以某种方式提及此模块,但如何?我在我的目录树(尤其是 Products/myproduct/profiles
下)搜索了 exportimport
、模块名称和其他几个字符串,但我找不到任何东西;也许曾经有过整合,但被打破了......
那么我该如何使这个 portal_user_catalog
工作呢?
谢谢!
更新:另一个debug
会话表明问题的根源是一些transaction
问题:
>>> portal = app.Plone
>>> puc = portal.portal_user_catalog
>>> puc._catalog()
[]
>>> profiles_folder = portal.some_folder_with_profiles
>>> for o in profiles_folder.objectValues():
... puc.catalog_object(o)
...
>>> puc._catalog()
[<Products.ZCatalog.Catalog.mybrains object at 0x69ff8d8>, ...]
portal_user_catalog
的人口不会持续存在;在 debug
会话结束并开始 fg
之后,大脑就消失了。
看来问题确实与交易有关。
我有
import transaction
...
class Browser(BrowserView):
...
def processNewUser(self):
....
transaction.commit()
以前,但显然这还不够好(and/or 可能做得不正确)。
现在我使用 transaction.begin()
显式开始事务,使用 transaction.savepoint()
保存中间结果,使用 transaction.abort()
显式中止事务以防出现错误 (try
/ except
), 且最后恰好有一个transaction.commit()
, 则成功。似乎一切正常。
当然,Plone仍然没有考虑到这个非标准目录;当我 "clear and rebuild" 它时,它是空的。但对于我的应用程序来说,它工作得很好。
我正在为我的 Plone 站点创建一个分支(已经很长时间没有分支了)。该站点有一个用于用户配置文件的特殊目录对象(一种特殊的基于原型的对象类型),称为 portal_user_catalog
:
$ bin/instance debug
>>> portal = app.Plone
>>> print [d for d in portal.objectMap() if d['meta_type'] == 'Plone Catalog Tool']
[{'meta_type': 'Plone Catalog Tool', 'id': 'portal_catalog'},
{'meta_type': 'Plone Catalog Tool', 'id': 'portal_user_catalog'}]
这看起来很合理,因为用户配置文件没有 "normal" 对象的大部分索引,但有一小部分自己的索引。
因为我找不到如何从头开始创建这个对象的方法,所以我将它从旧站点(如 portal_user_catalog.zexp
)导出并导入到新站点。这似乎可行,但我无法将对象添加到导入的目录中,甚至无法显式调用 catalog_object
方法。相反,用户配置文件被添加到标准 portal_catalog
.
现在我在我的产品中发现了一个模块,似乎可以达到目的 (Products/myproduct/exportimport/catalog.py
):
"""Catalog tool setup handlers.
$Id: catalog.py 77004 2007-06-24 08:57:54Z yuppie $
"""
from Products.GenericSetup.utils import exportObjects
from Products.GenericSetup.utils import importObjects
from Products.CMFCore.utils import getToolByName
from zope.component import queryMultiAdapter
from Products.GenericSetup.interfaces import IBody
def importCatalogTool(context):
"""Import catalog tool.
"""
site = context.getSite()
obj = getToolByName(site, 'portal_user_catalog')
parent_path=''
if obj and not obj():
importer = queryMultiAdapter((obj, context), IBody)
path = '%s%s' % (parent_path, obj.getId().replace(' ', '_'))
__traceback_info__ = path
print [importer]
if importer:
print importer.name
if importer.name:
path = '%s%s' % (parent_path, 'usercatalog')
print path
filename = '%s%s' % (path, importer.suffix)
print filename
body = context.readDataFile(filename)
if body is not None:
importer.filename = filename # for error reporting
importer.body = body
if getattr(obj, 'objectValues', False):
for sub in obj.objectValues():
importObjects(sub, path+'/', context)
def exportCatalogTool(context):
"""Export catalog tool.
"""
site = context.getSite()
obj = getToolByName(site, 'portal_user_catalog', None)
if tool is None:
logger = context.getLogger('catalog')
logger.info('Nothing to export.')
return
parent_path=''
exporter = queryMultiAdapter((obj, context), IBody)
path = '%s%s' % (parent_path, obj.getId().replace(' ', '_'))
if exporter:
if exporter.name:
path = '%s%s' % (parent_path, 'usercatalog')
filename = '%s%s' % (path, exporter.suffix)
body = exporter.body
if body is not None:
context.writeDataFile(filename, body, exporter.mime_type)
if getattr(obj, 'objectValues', False):
for sub in obj.objectValues():
exportObjects(sub, path+'/', context)
我尝试使用它,但我不知道它应该如何完成;
我不能称之为 TTW(我应该尝试发布方法吗?!)。
我在 debug
会话中尝试过:
$ bin/instance debug
>>> portal = app.Plone
>>> from Products.myproduct.exportimport.catalog import exportCatalogTool
>>> exportCatalogTool(portal)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File ".../Products/myproduct/exportimport/catalog.py", line 58, in exportCatalogTool
site = context.getSite()
AttributeError: getSite
所以,如果这是要走的路,看来我需要一个 "real" 上下文。
更新: 为了获得这个上下文,我尝试了 External Method
:
# -*- coding: utf-8 -*-
from Products.myproduct.exportimport.catalog import exportCatalogTool
from pdb import set_trace
def p(dt, dd):
print '%-16s%s' % (dt+':', dd)
def main(self):
"""
Export the portal_user_catalog
"""
g = globals()
print '#' * 79
for a in ('__package__', '__module__'):
if a in g:
p(a, g[a])
p('self', self)
set_trace()
exportCatalogTool(self)
然而,当我调用它时,我得到了与 main
函数的参数相同的 <PloneSite at /Plone>
对象,它没有 getSite
属性。也许我的站点没有正确调用此类外部方法?
或者我是否需要在 configure.zcml
中以某种方式提及此模块,但如何?我在我的目录树(尤其是 Products/myproduct/profiles
下)搜索了 exportimport
、模块名称和其他几个字符串,但我找不到任何东西;也许曾经有过整合,但被打破了......
那么我该如何使这个 portal_user_catalog
工作呢?
谢谢!
更新:另一个debug
会话表明问题的根源是一些transaction
问题:
>>> portal = app.Plone
>>> puc = portal.portal_user_catalog
>>> puc._catalog()
[]
>>> profiles_folder = portal.some_folder_with_profiles
>>> for o in profiles_folder.objectValues():
... puc.catalog_object(o)
...
>>> puc._catalog()
[<Products.ZCatalog.Catalog.mybrains object at 0x69ff8d8>, ...]
portal_user_catalog
的人口不会持续存在;在 debug
会话结束并开始 fg
之后,大脑就消失了。
看来问题确实与交易有关。 我有
import transaction
...
class Browser(BrowserView):
...
def processNewUser(self):
....
transaction.commit()
以前,但显然这还不够好(and/or 可能做得不正确)。
现在我使用 transaction.begin()
显式开始事务,使用 transaction.savepoint()
保存中间结果,使用 transaction.abort()
显式中止事务以防出现错误 (try
/ except
), 且最后恰好有一个transaction.commit()
, 则成功。似乎一切正常。
当然,Plone仍然没有考虑到这个非标准目录;当我 "clear and rebuild" 它时,它是空的。但对于我的应用程序来说,它工作得很好。