开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜