[Zope3-Users] Oh no, doncha violate the o-v-p

Christian Lueck christian.lueck at ruhr-uni-bochum.de
Thu Sep 29 12:11:51 EDT 2005


Hi,

I found a relatively easy way to write an addview for multiple objects.
As this violates the object view paradigm (o-v-p) I'd like to have your
expert critiques/comments: Are there any risks regarding the violation?

The task was to have one view V to create two objects A and B. A is a
container, B is contained in A. There must not be an empty A container,
one item at least.

I wrote a viewclass based on formlib, which makes it very easy to
generate fields from multiple schemas. (But this flexibility seems to be
intented for cases different from mine...)

The thing is to customize the createAndAdd method to call create- and
add-methods specified for both A and B (see sourcecode of
formlib.from.AddFormBase).

In my concrete case 'A' is 'Example' and 'B' is 'ExampleResourceSet'.
The major problem was the addExampleResourceSet method (see below last
method of code).


class ExampleAddView(form.AddForm):

    <snip>

    def createAndAdd(self, data):
        
        obExample = self.createExample(data)
        obExampleResourceSet = self.createExampleResourceSet(data)

        notify(ObjectCreatedEvent(obExample))
        notify(ObjectCreatedEvent(obExampleResourceSet))

        instExample = self.addExample(obExample)
        instExampleResourceSet =
self.addExampleResourceSet(obExampleResourceSet, instExample)

        return instExample, instExampleResourceSet

    def createExample(self, data):
        """Pass Example related form values to an Example factory."""
        example_factory = zapi.getUtility(IFactory,
                                          u"example.ExampleFactory_AddForm")
        example = example_factory(
            einheitsacht = self.session_data['einheitsacht'],
            example_orig_lang = data['example_orig_lang'],
            example_x_lang = [])
        return example

    def createExampleResourceSet(self, data):
        example_resource_set_factory = zapi.getUtility(IFactory,
                                                      
u"example.ExampleResourceSetFactory_AddForm")
        example_resource_set = example_resource_set_factory(
            resource = self.session_data['resource'],
            example = data['example'],
            quotation = data['quotation'],
            page = data['page'])
        return example_resource_set

    _finished_add = False
    _finished_addExample = False
    _finished_addExampleResourceSet = False

    _example_name = u"__stillunkown__"

    def addExample(self, object):
        ob = self.context.add(object)
        self._finished_addExample = True
        if self._finished_addExample and
self._finished_addExampleResourceSet:
            self._finished_add = True
        return ob

    def addExampleResourceSet(self, content, container):
        """PROBLEM: no IAdding regarding container.
        So code this following the lines of the IAdding implementation
        in zope.app.container.browser.adding.Adding ."""

        name = None

        # check precondition
        checkObject(container, name, content)
        
        if self._finished_addExample:

            # choose a name
            if IContainerNamesContainer.providedBy(container):
                name = INameChooser(container).chooseName('', content)
            else:
                """Exception since we don't want to choose a name by
hand."""
                err = "container %s does not implement
IContainerNamesContainer" % container
                raise Exception_ExampleAddView, err

            # Create the object.
            container[name] = content

            # set status tings
            self._finished_addExampleResourceSet = True
            self._finished_add = True

            return container[name]

        else:
            err = "Unable to create ExampleResourceSet _before_ Example"
            raise Exception_ExampleAddView, err

    <snip>

Note: Both content classes implement IContainerNamesContainer.

In the addExample method the codeline
ob = self.context.add(object)
calls the add method defined by IAdding (or rather its implementation,
the magic /+/ ;). But since there is no IAdding context regarding the
new created Example object we have to 'hardcode' the add method for the
ExampleResourceSet object. I did that following and adapting the lines
of the IAdding implementation of zope.app.container.browser.adding.Adding.



Best regards,
Christian


PS. If you wonder about the class name 'Example' -- the application is
supposed to be a database to collect examples and metaphors (rhetorical
figures) and will be part of a project located at the department for
german language and literature at the Ruhr-University Bochum, germany.


More information about the Zope3-users mailing list