Advanced Blueprint Tips#

Iterator Stages#

This training only focused on one stage, but iterators have three stages! Learn more about this at

Migrating Users & Groups#

Jsonify will not export user and group information. These will need to be exported separately. See Users & Groups Migration for example code.

Updating Rich Text#

When updating your sites, you may have add-ons that will change in the process. This can adjust text that appears in the body text of pages. Check out PyQuery to help parse the HTML for you. Here's an example that updates oembed tags to uwosh.snippets style:

def new_snippet(self, itemuid):
     return '<span class="snippet-tag snippet-tag-html_snippet" \
         contenteditable="false" data-type="snippet_tag" \
         data-snippet-id="{0}" data-header="">\

 def __iter__(self):
     for item in self.previous:
         if 'text' not in item:
             yield item
         if 'oembed oembed-responsive' not in item['text']:
             yield item
         txt = PyQuery(item['text'])
         full_text = txt.html()
         for snippet in txt(".oembed"):
             link = PyQuery(snippet)
             href = link("a").attr("href")
             if not href:
             if 'resolveuid' in href:
                 linkuid = href.replace('resolveuid/', '')
                 if not api.content.get(UID=linkuid):
                     # leave link as is if we can't find the new one
                 # replace link with new snippet
                 full_text = full_text.replace(PyQuery(snippet).outer_html(), self.new_snippet(linkuid))
                 html_snippets = api.content.find(path='/Plone/' + href)
                 if not html_snippets:
                 new = self.new_snippet(html_snippets[0].UID)
                 full_text = full_text.replace(PyQuery(snippet).outer_html(), new)
         item['text'] = full_text

Taking parameters in custom blueprints#

See how the PartialCommit blueprint does this.

In the pipeline, we have:

blueprint = collective.jsonmigrator.partialcommit
every = 1000

Here is the blueprint. options contains any extra parameters that have been passed in. If every is not in the options, 100 is used as the default.

class PartialCommit(object):

    def __init__(self, transmogrifier, name, options, previous):
        self.previous = previous
        self.step = int(options.get('every', 100))

    def __iter__(self):
        count = 1
        for item in self.previous:
            yield item
            if count % self.step == 0:
      'Committed after %s' % count)
            count += 1