[Zope-CMF] Re: Add forms and menus

Robert Niederreiter rnix at squarewave.at
Wed Jul 16 04:22:05 EDT 2008


Am Dienstag, den 15.07.2008, 22:34 +0100 schrieb Martin Aspeli:
> Daniel Nouri wrote:
> > Daniel Nouri writes:
> > 
> >> Robert Niederreiter writes:
> > 
> >>> yuppie writes:
> > 
> >>>> I like pretty URLs, and 'foo/+/<MyPortalType>' looks much prettier than 
> >>>> the URLs needed with my approach:
> >>>>
> >>>>    foo/<AddViewName>?form.portal_type=<MyPortalType>
> >>>>
> >>>> Your proposal has some advantages. On the other hand this requires to 
> >>>> create CMF specific code and patterns in a place where a more generic 
> >>>> solution also works.
> >>> it does not if you call a formfactory inside the traverser, so it's
> >>> hoohable for CMF, Plone or whatever even with different formlib
> >>> implementations.
> >>>
> >>> like:
> >>>
> >>> formfactory = getAdapter(context,
> >>>                          IFormFactory,
> >>>                          name='factoryNameFromFti')
> >>> return factory()
> >>>
> >>> which handles all the magic in there. just a thought.
> >> If I understand this correctly, it should be more like:
> >>
> >>   formfactory = getMultiAdapter((context, request),
> >>                                 IAddForm,
> >>                                 name='factoryNameFromFti')
> > 
> > My suggestion is rubbish.  First, it should be 'form', not
> > 'formfactory'.  Then, I realize it's not the same pattern since your
> > factory is supposed to do some work before it passes on control (I
> > believe?) whereas mine is the add form class itself.
right. it was meant as a step in between to fit yuppies suggestion on
beeing generic at this point.

> > 
> > Both patterns require the same amount of registrations.  As many for
> > IFormFactory as for IAddForm.  What's worse is that the implementations
> > will have a hard time to work reusably without the portal type name,
> > which they're registered with.
> > 
> > What about the traverser does this:
> > 
> >     try:
> >         view = getMultiAdapter((context, request),
> >                                IAddForm, name=factory_name)
> >     except ComponentLookupError, e:
> >         view = getMultiAdapter((context, request), IAddForm)
> > 
> >     view.factory_name = factory_name
> >     return view()
> > 
> > In this case, the adapter/form would actually have a chance to work for
> > more than one portal type.
> > 
> > How does this sound?
even better.

> 
> It still feels a bit fishy to me.
> 
> I don't really see why you need a traverser *unless* you're trying to 
> have a single add form implementation that covers multiple types.
i.e. if you have one content type, i.e. a folder, but you want to use
exactly this type with different workflows, names, icons, then this
makes indeed sence.

here you might simply add another fti, and its done. adding such a type
is then either invoked like @@add/Folder or @@add/AnotherFtiForFolder,
but both return the same form.

>  You 
> may of course have that, and maybe it's helpful to let people write 
> that, but I think most people would prefer to write "plain" add views 
> that use the standard z3c.form patterns.
its possible anyway, isn't it? the advantage is that there's one way how
adding works in general. and the discussion is still about implementing
a generic adding mechanism in CMF. as i pointed in a previous post,
there should be the possibility to do customization. so as convention it
might be done this way.

* lookup fti for ``portal_type``

* have a look if theres a custom view set.

* if so, do lookup with this name

* if not, try lookup with ``portal_type`` as name

* finally do general lookup if others failed.

thats also why i tried to introduce IFormFactory, because the traverser
might not need to know too much. but thats maybe a bit too far...?

> 
> For something like Dexterity, where we explicitly want to support 
> "generic" content with a schema that varies according to runtime 
> configuration, this is more of an issue. But even there, the intention 
> is that whilst the framework has a few hooks like this so that it works 
> with content that's more malleable, it doesn't force you to use 
> unconventional patterns if you do something yourself on the filesystem.
the goal should be the various IFormFactory hooks, so you might not need
to change the way you write addforms in general, but to provide a
specific IFormFactory implementation for a specific framework.
(dexterity, devilstick, archetypes, whatever).

as an alternative the magic could be done in the traverser directly, but
then there must be different traversers for each framework and different
'add' browserpages where those traversers could be bound to. this would
then look like this for invoking:

@@+cmf/``portal_type``
@@+ds/``portal_type``
@@+dx/``portal_type``
@@+at/``portal_type``
...

which of them to call in the add dropdown must be stored then i the fti.

> 
> In the case above, you end up having to register your form as a 
> particular adapter rather than a browser view. That's fairly unnatural, 
> and also doesn't necessarily deal with things like security settings. It 
> makes the add view quite different to write than the edit view, too.
all the forms can be registered as browserpages anyway (and should!).
there's no difference if you call it via the browser, or get it inside
the traverser with getMultiAdapter and return this one. even the
security settings are considered then imo.

> 
> Martin
> 

Robert



More information about the Zope-CMF mailing list