Loop through a bunch of folderish content, which may be itself folderish?
Suppose I have a content type, Folder, with 4 items.
+ MyObject
- Child1
- Child2
- Child3
+ Child4
- Child5
- Child6
Suppose I have another content type (let's call it Alias
). This Alias
is mainly a reference to another object but folderish: it can contain a bunch of other aliases. I'm going to use -->
to indicate this reference in the following tree representations.("Reference" is mainly an attribute called "reference" that rec开发者_运维知识库eives the UID from the target object).
Suppose MyAlias
now references my MyObject
.
+ MyAlias --> MyObject
- (Nothing)
When referencing to MyObject
, MyAlias
doesn't know that MyObject
is a Folder, so the internal MyAlias children don't exist. I need to loop through everyone, and create, manually, an Alias inside MyAlias
, that is a reference (having the same structure) to MyObject
children. A little tree showing what should happen:
+ MyAlias --> MyObject
- Alias --> Child1
- Alias --> Child2
- Alias --> Child3
+ Alias --> Child4
- Alias --> Child5
- Alias --> Child6
I would like to know the best way to iterate through MyObject
items, and create the same structure with another objects, using some kind of loop and using invokeFactory
in a subscriber. In the end, I would have BOTH trees existing: one of the actual Folder and children, and another of references to this same Folder and children.
(Summarizing: something like collective.alias, but in a really primitive form, just folders an documents, since I can't use collective.alias.)
The most elegant and Pythonic solution is to write a recursive generator. Assuming this is a method:
def iter_preorder(self):
yield self
# check for folderishness here if a non-folderish
# node may have children as well
for x in self.children:
for y in x.iter_preorder():
yield y
Then
for x in tree.iter_preorder():
do_action(x)
This way, you don't actually have to wrap your action into a function/callable and there's no inversion of control.
Recursivity may help
def do_action(child):
if child.isfolder():
for i in child:
do_action(i)
else:
child.setSomething()
do_action(MyObject)
Why would you not use the catalog? The catalog exists for solving these problems fast and securely for you, so that you can concentrate on things that matter. So, to find all the objects in some path:
ct = getToolByName(context, 'portal_catalog')
path = '/'.join(context.getPhysicalPath())
brains = ct.searchResults(path=path)
You can of course filter more in your query. Then,
for brain in brains:
obj = brain.getObject()
obj.setSomething()
The catalog is your friend, read how to use it.
It sounds like you may be trying to do a content type migration. If that's the case, take a look at Products.contentmigration.
精彩评论