Change 'klass' for dexterity content types

Hi,

I want to change my content type with base class 'klass':

-    <property name="klass">plone.dexterity.content.Item</property>                                   
+    <property name="klass">plone.dexterity.content.Container</property>

Does it make for me a lot things to check?
Will be reindexing for content type enough?

Best regards,
Bogdan.

The most important thing to realize is that this will not update any
existing objects in the database. Only new objects will have the new class.
If you need to switch old objects, you'll need to write a migration.

If you are interested in just changing the class of your existing dexterity content, I once did something like this:

1 Like

Dear Steve,

Could you please give me an example of this kind migration for updating old dexterity objects?

Best regards,
Bogdan.

Dear Ale,

It is actually I am looking for.
Thank you very much I am going to try.

Best regards,
Bogdan.

No problem, let me know if you found any problem.

Dear Ale,

I found an issue.
When you del object it runs also handlers which subscribed on remove events, in my case it runs event from p.a.discussion to clean comments.

Otherwise here https://teamspace.upiq.org/trac/wiki/DexterityClassMigration, there it is using parent_folder._delOb(obj.id) to remove object and in this case it doesn't clean comments.

I am finding issues which can happen in this case.

Best regards,
Bogdan.

Very good! Did not run in that issue :smile:
Thanks for sharing!

I have a good news I optimized script to prevent all unnessesary actions to migrate clear and safety.

obj_id = obj.getId()

parent = obj.__parent__
parent._delOb(obj_id)
from plone.dexterity.content import Container
obj.__class__ = Container
parent._setOb(obj_id, obj)

from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2Base
BTreeFolder2Base._initBTrees(obj)

obj.reindexObject(idxs=['is_folderish', 'object_provides', ])
2 Likes

back here using Plone 5.2 with an update:

add to this

obj = obj.aq_self

before altering the __class__ and calling parent._setOb()

Without that, my changes weren't surviving a restart.

1 Like

I'm using Plone 5.2, and aq_self was not required, and when I tried the parent was empty, so it was useless.

I installed the collective.folderishtypes addon, and it works fine when creating new items.
Now I'd like to convert all events to folderish events. I can't find a solution.
I seeking help to debug this script that I run from a Plone debug console (running iPython):

from plone import api
from Products.CMFCore.utils import getToolByName
from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2Base
from collective.folderishtypes.dx.content import FolderishEvent
import transaction

portal = api.portal.get()

catalog = getToolByName(portal, 'portal_catalog')
brains = portal.portal_catalog(portal_type='Event')
for brain in brains:
    obj = brain.getObject()
    if obj.__class__ == FolderishEvent and obj.meta_type == 'Dexterity Container' : continue
    obj_id = obj.getId()
    parent = obj.__parent__
    parent._delOb(obj_id)
    obj.__class__ = FolderishEvent
    obj.meta_type = 'Dexterity Container'
    parent._setOb(obj_id, obj)
    BTreeFolder2Base._initBTrees(obj)
    transaction.commit()
    obj.reindexObject(idxs=['is_folderish', 'object_provides', ])
    transaction.commit()
    url = obj.absolute_url()
    print(f"{obj_id} = {obj.__class__}, {obj.portal_type}, {url}")
    break

I run it a few times to convert a few events, then I run the plone instance to check if the events were successfully converted to folderish events (appending /folder_content to the url of converted events). I get error pages that says " This page does not seem to exist…"

Why??

Edit: I gave up and used another method:

  • exported the site to json files (using collective.jsonify)
  • deleted all events and news
  • re-imported all of them from json files (with collective.transmogrifier)
  • reconnected all translations