Appending data to an AT Field using transmogrifier

634 views Asked by At

I have a CSV file of data like this:

1, [a, b, c]
2, [a, b, d]
3, [a]

and some Plone objects which should be updated like this:

ID, LinesField
a, [1,2,3]
b, [1,2]
c, [1]
d, [2]

So, to clarify, the object with the id a is named on lines 1, 2 and 3 of the CSV, and thus the LinesField property of object a needs to have those line ids (the first number on the line) listed.

Ideally I'd like to use Transmogrifier to import this information (and avoid doing any manipulation in Excel beforehand), and I can see two ways, theoretically of doing this, but I can't work out how to do this in practice. I'd be grateful for some pointers to examples. I think that either I need to transform the entire pipeline so that the items reflect the structure of my Plone objects and then use the ATSchemaUpdater blueprint, but I can't see any examples on how to add items to the pipeline (do I need to write my own blueprint?) Or, alternatively I could loop through the items as they exist and append the value in the left column to the items in the list in the right. For that I need a way of appending values with ATSchemaUpdater rather than overwriting them - again, is there a blueprint for that anywhere?

Here's a few sample csv lines:

"Name","Themes"
"Bessie Brown","cah;cab;cac"
"Fred Blogs","cah;cac"
"Dinah Washington","cah;cab"

The Plone object will be a theme and the lines field a list of names:

cah, ['Bessie Brown', 'Fred Boggs' etc etc]
1

There are 1 answers

2
hvelarde On

I'm not pretty sure you want to read the CVS file using transmogrifier, but I think you can create a section to insert these values to the items in the pipeline using a function like this:

def transpose(cvs):
    keys = []
    [keys.extend(v) for v in cvs.values()]
    keys = set(keys)

    d = {}
    for key in keys:
        values = [k for k, v in cvs.iteritems() if key in v]
        d[key] = values

    return d

In this context, cvs is {1: ['a', 'b', 'c'], 2: ['a', 'b', 'd'], 3: ['a']}; keys will contain all possible values set(['a', 'c', 'b', 'd']); and d will be what you want {'a': [1, 2, 3], 'c': [1], 'b': [1, 2], 'd': [2]}.

Probably there are better ways to do it, but I'm not a Python magician.

The insert section could look like this one:

class Insert(object):
    """Insert new keys into items.
    """
    classProvides(ISectionBlueprint)
    implements(ISection)

    def __init__(self, transmogrifier, name, options, previous):
        self.previous = previous
        self.new_keys = transpose(cvs)

    def __iter__(self):
        for item in self.previous:
            item.update(self.new_keys)
            yield item

After that you can use the SchemaUpdater section.