Plone,Archetypes:将TextField从text / plain更改为text / html

时间:2016-03-02 13:24:15

标签: python plone archetypes plone-4.x

我有一系列Plone网站,它们使用基于Archetypes的内容。

我有一些TextField需要从text/plain更改为text/html;说,架构剪断了

TextField(
      name='summary',
      default='',
      read_permission=Access_contents_information,
      default_content_type='text/plain',
      allowable_content_types=('text/plain',),
      storage=AnnotationStorage(migrate=True),
      widget=TextAreaWidget(
          label=_('my_label_summary',
                  default='Summary'),
          i18n_domain='plone',
      ),
  ),

应该改为

TextField(
      name='summary',
      default='',
      read_permission=Access_contents_information,
      default_content_type='text/html',
      default_output_type='text/html',
      allowable_content_types=('text/html',),
      storage=AnnotationStorage(migrate=True),
      widget=RichWidget(
          label=_('my_label_summary',
                  default='Summary'),
          i18n_domain='plone',
      ),
  ),

由于物品的数量很少,我愿意接受受影响区域的临时丑陋外观(例如折叠的线路断裂);更重要的是拥有可视化编辑器(使用可切换的内容类型对我不起作用)。

最好的解决方案当然是将当前text/plain字段原样使用,并且在即将编辑对象时,将它们转换为合理的text/html等效字符,然后可以用可视化编辑器编辑(CKEditor,在我的例子中)。

但是,如果我只是使用更改的架构编辑对象,则可视编辑器看起来很好,但存储的文本被<p> / </p>标记包围并解释为text/plain

我找到了/archetype_tool/manage_updateSchemaForm,但更新了我班级的架构并没有帮助。

我找到https://plone.org/products/archetypes/documentation/old/ArchetypesDeveloperGuide/,但这看起来既不完整又过时。

任何指针?谢谢!

更新

因为这不符合评论: 我现在创建了一个upgrades子包; configure.zcml

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
    i18n_domain="plone">

    <genericsetup:upgradeStep
        source="*"
        destination="1001"
        title="text/html fields for MyType"
        profile="Products.myproduct:default"
        handler=".to_1001.fix_mimetypes"/>

</configure>

模块代码(to_1001.py):

import logging
from Products.CMFCore.utils import getToolByName
from ..tools.log import getLogSupport

logger, debug_active, DEBUG = getLogSupport(fn=__file__)

def htmlify_attribute(o, attr_name, brain=None, default=u''):
    """
    Change MIME type of a TextField to text/html
    """
    attr = getattr(o, attr_name, None)
    changed = False

    brain_url = (brain is not None
                 and brain.getURL()
                 or None)
    if not attr:
        mutator = o.getField(attr_name).getMutator(o)
        mutator(default)
        attr = getattr(o, attr_name, None)
        changed = True

    convert = False
    mimetype = getattr(attr, 'mimetype', 'text/plain')
    if mimetype != 'text/html':
        if brain_url is not None:
            logger.info('Fixing MIME type of %(attr_name)s'
                        ' for %(brain_url)s', locals())
        setattr(attr, 'mimetype', 'text/html')
        changed = True

    return changed

def fix_mimetypes(context):
    """
    text/plain --> text/html for some MyType fields
    """
    pc = getToolByName(context, 'portal_catalog')
    TYPES = ['MyType']
    brains = pc.unrestrictedSearchResults(portal_type=TYPES)
    total = len(brains)
    MASK = 'Fixing MIME types for %(total)d %(TYPES)s objects'
    logger.info(MASK + ' ...', locals())
    cnt = 0

    import pdb; pdb.set_trace()
    for brain in brains:
        obj = brain.getObject()
        if htmlify_attribute(obj, 'summary', brain):
            cnt += 1

    if cnt or True:
        logger.info('%(cnt)d objects changed', locals())
    logger.info(MASK + ': DONE', locals())
    return ('Done '+MASK) % locals()

由于我的产品缺少special profile version,因此我创建了一个.../profiles/default/metadata.xml文件,并将值设置为1000;因为在启动时没有发生任何事情,并且在QuickInstaller中没有发现任何特殊情况,我重新安装,然后将数字增加一个。

我的to_1001模块是在启动时导入的,正如我可以通过注册记录器看到的那样 (已记录);但它不是使用(因为我知道因为 pdb.set_trace()),既没有使用增加的版本号启动(bin/instance fg),也没有在QuickInstaller中重新安装时。

缺少什么? 这个升级步骤应该如何工作,即被触发?

2 个答案:

答案 0 :(得分:2)

您可能需要现有对象的升级步骤。例如,请参阅eea.soercontent evolve19.pyconfigure.zcml

要测试是否是这种情况,请在编写升级步骤之前,转到修改保存,而不进行任何更改。现在,如果再次进入“编辑”,则应该使用富文本编辑器。

答案 1 :(得分:1)

我现在已经将这个代码用于两个客户端,以初始化新的富文本字段。我想如果他们是旧的或新的领域并不重要。此函数将内容实例作为输入。因此,您可以遍历目录大脑并传递此函数brain.getObject()

def initialize_rich_text_fields(instance):
    """New rich text fields should have mimetype text/html.

    Adapted from setDefaults in Archetypes BasicSchema.
    """
    default_output_type = 'text/x-html-safe'
    mimetype = 'text/html'
    schema = instance.Schema()
    for field in schema.values():
        # We only need to do this for fields with one specific mimetype.
        if not shasattr(field, 'default_output_type'):
            continue
        if field.default_output_type != default_output_type:
            continue
        # only touch writable fields
        mutator = field.getMutator(instance)
        if mutator is None:
            continue
        base_unit = field.getBaseUnit(instance)
        if base_unit.mimetype == mimetype:
            continue
        # If content has already been set, we respect it.
        if base_unit:
            continue
        default = field.getDefault(instance)
        args = (default,)
        kw = {'field': field.__name__,
              '_initializing_': True}
        kw['mimetype'] = mimetype
        mapply(mutator, *args, **kw)