---
myst:
html_meta:
"description": ""
"property=og:description": ""
"property=og:title": ""
"keywords": ""
---
# 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 {doc}`users-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](https://pypi.org/project/pyquery) to help parse the HTML for you.
Here's an example that updates oembed tags to [uwosh.snippets](https://pypi.org/project/uwosh.snippets/) style:
```python
def new_snippet(self, itemuid):
return '\
Snippet:[ID={0}]'.format(itemuid)
def __iter__(self):
for item in self.previous:
if 'text' not in item:
yield item
continue
if 'oembed oembed-responsive' not in item['text']:
yield item
continue
txt = PyQuery(item['text'])
full_text = txt.html()
for snippet in txt(".oembed"):
link = PyQuery(snippet)
href = link("a").attr("href")
if not href:
continue
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
continue
# replace link with new snippet
full_text = full_text.replace(PyQuery(snippet).outer_html(), self.new_snippet(linkuid))
else:
html_snippets = api.content.find(path='/Plone/' + href)
if not html_snippets:
continue
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:
```ini
[savepoint]
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.
```python
@provider(ISectionBlueprint)
@implementer(ISection)
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:
transaction.commit()
logging.info('Committed after %s' % count)
count += 1
```