I'm Exporting plone content with collecive.exportimport.
First observation is that the form-based export at the /@@export_content view is so much easier than the old command-line and script way. Thank you.
My problem is "Rich Text Fields need to be exported differently". And this solution can work for any field, really, but the Rich Text serializer is probably the most in-demand customization.
The solution is to first add a customization to the exporter: GitHub - collective/collective.exportimport: Export and import content and other data from and to Plone
Once that's done, we add a configure.zcml and serializer.py to our own customization module:
in serializer.py - add the new field seializer. Follow the example in collective.exportimport serializer.py, or go deeper by looking at the restapi serialzers if you wish:
This is a proof of concept, so I just want to hit a debug, and then do whatever the system was doing before I mucked with it. my pattern is to just call debug and then super() when I'm at this stage.
(I left out a bunch of imports for brevity)
in my custom serialzer.py:
from collective.exportimport.serializer import RichttextFieldSerializerWithRawText
@adapter(IRichText, IDexterityContent, IRawRichTextMarker)
class RichTextFieldSerializerWithImageUrls(RichttextFieldSerializerWithRawText):
def __call__(self):
import pdb; pdb.set_trace()
super(RichTextFieldSerializerWithImageUrls).__call__(self)
And register it in your custom configure.zcml
<adapter factory=".serializer.RichTextFieldSerializerWithImageUrls" />
Restart your plone instance and you should get this error - which means you're on the right path!
raise ConfigurationConflictError(conflicts)
zope.configuration.config.ConfigurationConflictError: Conflicting configuration actions
Now, all we have to do is be a bit more specific about what interfaces our adapter adapts. I chose to be specific to MY Dextiery Content Type rather than All Dexterity Content Types (It's called a story):
So, IDextieryContent changes to IStory - which is the schema definition in my own custom Dexterity Type.
from rfasite.content.content.story import IStory
@adapter(IRichText, IStory, IRawRichTextMarker)
class RichTextFieldSerializerWithImageUrls(RichttextFieldSerializerWithRawText):
def __call__(self):
import pdb; pdb.set_trace()
super(RichTextFieldSerializerWithImageUrls).__call__(self)
And now "stories" with "Rich Text Fields" get special treatment. I will now replace that __call__()
method with what I want!
MY QUESTION
I find it tedious to specify a specific dexterity content type here. what I WANT to do is add an installation layer interface or a browser layer interface - like "My custom exporter is installed, so it's more specific"
@adapter(IMyContentExporterLayer, IRichText, IDexterityContent, IRawRichTextMarker)
But that adapter wasn't being found during export. getmultiadapter() wasn't finding it. How can I accomplish registering an adapter that overrides the default in colletive.exportimport using an entire installation layer?