【问题标题】:Plone, Archetypes: Change a TextField from text/plain to text/htmlPlone,Archetypes:将 TextField 从 text/plain 更改为 text/html
【发布时间】:2016-03-03 18:40:41
【问题描述】:

我有一系列使用基于原型的内容的 Plone 网站。

我有一些TextFields 需要从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 中没有观察到任何特殊情况,所以我重新安装了,然后将数字增加了 1。

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

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

【问题讨论】:

    标签: python plone archetypes plone-4.x


    【解决方案1】:

    您可能需要对现有对象进行升级。参见例如 eea.soercontent evolve19.pyconfigure.zcml

    要测试是否是这种情况,在编写升级步骤之前,请转到编辑保存而不做任何更改。现在,如果您再次转到“编辑”,您应该已经准备好富文本编辑器了。

    【讨论】:

    • 是的,我想我需要一个升级步骤;我会调查一下。我的主要问题不是获取富文本编辑器,而是获取正确的内容类型。
    • 我通过创建升级步骤的努力更新了我的问题。这应该如何工作,即被触发?
    • 将版本1001放入profiles/default/metadata.xml,然后您的升级步骤应该出现在Site Setup &gt; Add-ons或通过ZMI:portal_setup &gt; manage_upgrades
    【解决方案2】:

    我现在已经为两个客户端使用了这段代码来初始化新的富文本字段。我想它们是旧领域还是新领域都没有关系。此函数将内容实例作为输入。所以你可以遍历目录大脑并传递这个函数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)
    

    【讨论】:

    • 啊,有趣(虽然可能不是完全我需要的)。是否应该将text/x-html-safe 用作可能包含text/plaintext/html每个 字段的default_output_type
    • 对不起 - 我犹豫了一秒钟太久来编辑以前的评论......所以text/x-html-safe 是关于剥离危险的 HTML 标签,建议用于任何用户贡献的内容。将简单的text/plain(文本段落和项目符号列表)转换为 HTML 并不是偶然的标准转换,对吗?很抱歉 - 我的对象中是 text/plain,而不是 text/structured 或类似...
    • Plone 附带 Products.PortalTransforms 中的 portal_transform 工具。您可以使用它从一种 mime 类型转换为另一种。