Re: [Zope-CMF] Re: Add forms and menus

2008-07-17 Thread Robert Niederreiter

Am Mittwoch, den 16.07.2008, 15:57 + schrieb Martin Aspeli:
 Daniel Nouri [EMAIL PROTECTED] writes:
 
  
  Robert Niederreiter writes:
  
   Am Mittwoch, den 16.07.2008, 16:24 +0200 schrieb Daniel Nouri:
   Where would we need overrides.zcml?
  
   in the case where ICMFAddForm is no longer my interface to look up. then
   i have to overwrite the traverser.
  
  Why would ICMFAddForm no longer be the interface to look up?  It's the
  the only type of add form that promises to do something meaningful with
  the 'portal_type' attribute that's set on it in the traverser.
 
 And even if it weren't - we shouldn't hardcode the traversal adapter. We 
 should
 make this a convenient implementation option. The actual URL of the add view
 should configurable via a TALES expression, which means that it can be written
 without the @@add bit.

sure

 
 Martin
 
 ___
 Zope-CMF maillist  -  Zope-CMF@lists.zope.org
 http://mail.zope.org/mailman/listinfo/zope-cmf
 
 See http://collector.zope.org/CMF for bug reports and feature requests
-- 
Robert Niederreiter
IT-Architecture  Engineering
Aflingerstraße 7
A-6176 Völs
+43 699 160 20 192
+43 512 89 00 77

Squarewave Computing WEB APPLICATIONS,  ZOPE,  PLONE, HOSTING
BlueDynamics Allianceproduction: concept, development, design
http://squarewave.at consulting: analysis, coaching, training
http://bluedynamics.com  management: projects, process, community


___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-17 Thread Robert Niederreiter

Am Mittwoch, den 16.07.2008, 15:24 + schrieb Martin Aspeli:
  it's not that big architectual change. everything else discussed is
  possible anyway. i would rather call it a feature than a design change
  (since the change happens anyway).
 
 I think it's a fairly big shift to assume that the FTI has knowledge of the
 schema of the type. It's not necessarily a *bad* idea (at least I don't think
 so, since this is basically how Dexterity works :-), but right now, FTI 
 doesn't
 have any notion of a schema. With this change, you're effectively dictating 
 (or
 strongly suggesting) that all CMF types have a schema and that this is the
 basis for forms, and suggesting that forms aren't registered as independent
 views but rather inferred from this schema.
it was just a suggestion, so i have no problem if the fti does not know
about this, but still is imo a good place to store such an information. 

 
  we discuss the generic adding approach, we further discuss what has to
  be considered to be generic.
 
 I'm just not sure that generic is so good. If it's easy to make add- and edit-
 views (probably with convenience classes for CMFish container adding behavior)
 and obvious how to register them, then do you need more framework? At least 
 not
 in CMFCore.
 
 Better to leave that up to higher level frameworks to implement this type of
 generality.
 
  2 more properties on the fti (addforminterface, schemainterface), both
  are optional, but provide then the discussed and requested flexibility
  for different type implementations.
 
 Optional properties still need to be maintained and may still create confusion
 or conflicting assumptions. Here, we've invented two new concepts (the type 
 has
 a schema, the type has an interface that describes the add form). It may be 
 that
 more advanced frameworks need something a bit different, and so they'll have 
 to
 either overload or ignore those properties.
 
  if we do not consider this questions at this state, again the result
  will be stupid and ugly subclassing and incompatibility and bad readable
  code and overrides.zcml (which is one thing i really hate!).
 
 I don't know if that's true. Trying to solve all problems at the most basic
 level is probably not a good idea. Giving the right hooks probably is.
agree

 
 I think if we make the addview name used for the rendering of menus a TALES
 expression, then the traverser thing becomes a CMFDefault implementation 
 detail
 (not even CMFCore).
 
 Dexterity has its own FTI type. It will always need that, no matter how many
 hooks you have here. I have no problem with that, actually - GenericSetup 
 makes
 it easy. Dexterity does not need any overrides.zcml either. ;-)
 
  right, therefor you always have the possibility to write your own form
  implementation.
 
 I think it's a mark of bad framework design if that possibility really means
 throwing away most of the conventions and standard support and building up
 something else starting from a very low level. In that case, the framework's
 tried to too much application-level work that ends up being useless to the
 actual applications (like Plone), who then have to invent their own parallel
 framework to support their own slightly divergent use cases.
 
  i simply wonder why people should write code for default behaviour when
  there can be a default implementation.
 
 I don't think it's a safe assumption that *at the CMFCore level* we'll have a
 sensible default. It's a pretty big assumption that it's sensible for most
 applications to have a linear form that uses formlib's default widgets with no
 custom setup code for most types.
 
  i only want to point here to the plone portlets engine. why is it
  necessary to provide 4 (!) classes, a template and a zcml configuration
  for 1 portlet? thats imo too much, especially because people are
  familiar with and love the 'write-less-do-more' mentality, and adherence
  to a tradition is not automatically more productive or easier to
  understand.
 
 I can tell you why it's necessary in another thread. It's irrelevant here (and
 on this list).
i know that it's necessary, i also know why. i took this as an example,
nevertheless i like the portlets engine.

anyway my opinion is even here it would not be that big challange to
provide default implementations.

plone 3+ is in it's design and code organized much better than plone
2.5-, but also harder to understand for newbees since someone needs much
more base knowledge to adopt it. imo this should be considered a little
more when improving things. to keep not always the simplicity at
framework side but rather in using it from the developers and
integrators pov which was much about the success of plone. but thats
beyond this thread.

robert

 
 Martin
 
 ___
 Zope-CMF maillist  -  Zope-CMF@lists.zope.org
 http://mail.zope.org/mailman/listinfo/zope-cmf
 
 See http://collector.zope.org/CMF for bug reports and feature requests
-- 

[Zope-CMF] Re: Add forms and menus

2008-07-17 Thread Laurence Rowe

Charlie Clark wrote:


Am 15.07.2008 um 23:38 schrieb Martin Aspeli:

Actually, that's interesting... what purpose does 'initial view' serve 
in a world with add forms?


The same as it ever has - you redirect to the initial view from the 
add form because the add form is actually registered for the container 
(IFolderish object) and the initial view is called because the object 
itself hasn't been used.


Should we re-purpose this slightly to make it provide the add form 
view URL?



No, I think it has to be a separate property.


I'd be interested to hear what you are using this for (other than to 
redirect to the default view of the newly created object).


Laurence

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-17 Thread Charlie Clark


Am 17.07.2008 um 12:41 schrieb Laurence Rowe:

I'd be interested to hear what you are using this for (other than to  
redirect to the default view of the newly created object).



Not a lot if the truth be told apart from the fact that sometimes you  
might want to go to the metadata form, other times to an edit form and  
others straight to a public view.


This is the code in CMFDefault.formlib.form

def nextURL(self):
obj = self._added_obj
fti = obj.getTypeInfo()

message = translate(self.status, self.context)
if isinstance(message, unicode):
message = message.encode(self._getBrowserCharset())
return '%s/%s?%s' % (obj.absolute_url(), fti.immediate_view,
 make_query(portal_status_message=message))

I hope I'm not confusing initial and immediate views!

Charlie
--
Charlie Clark
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-938-5360
GSM: +49-178-782-6226



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-17 Thread Charlie Clark


Am 16.07.2008 um 17:24 schrieb Martin Aspeli:

I think it's a fairly big shift to assume that the FTI has knowledge  
of the
schema of the type. It's not necessarily a *bad* idea (at least I  
don't think
so, since this is basically how Dexterity works :-), but right now,  
FTI doesn't
have any notion of a schema. With this change, you're effectively  
dictating (or
strongly suggesting) that all CMF types have a schema and that  
this is the
basis for forms, and suggesting that forms aren't registered as  
independent

views but rather inferred from this schema.


Indeed. It is reasonable to expect a subclass to provide a set of  
FormFields but this is not the same as a schema. We have found being  
able to handle portal_type and schema or fields ie. an instance  
FormFields() in the super class to avoid repeated use of the somewhat  
cumbersome FormFields(TextLine(__name__...)) code.


we discuss the generic adding approach, we further discuss what has  
to

be considered to be generic.


I'm just not sure that generic is so good. If it's easy to make add-  
and edit-
views (probably with convenience classes for CMFish container adding  
behavior)
and obvious how to register them, then do you need more framework?  
At least not

in CMFCore.



Explicit is always better than implicit. This stuff really isn't a lot  
of work but it provides clarity and helps people understand what's  
going on and I think this is essential for any framework. Less magic  
is more power. ;-)


Charlie
--
Charlie Clark
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-938-5360
GSM: +49-178-782-6226



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-17 Thread Robert Niederreiter

Am Donnerstag, den 17.07.2008, 13:03 +0200 schrieb Charlie Clark:
 Am 16.07.2008 um 17:24 schrieb Martin Aspeli:
 
  I think it's a fairly big shift to assume that the FTI has knowledge  
  of the
  schema of the type. It's not necessarily a *bad* idea (at least I  
  don't think
  so, since this is basically how Dexterity works :-), but right now,  
  FTI doesn't
  have any notion of a schema. With this change, you're effectively  
  dictating (or
  strongly suggesting) that all CMF types have a schema and that  
  this is the
  basis for forms, and suggesting that forms aren't registered as  
  independent
  views but rather inferred from this schema.
 
 Indeed. It is reasonable to expect a subclass to provide a set of  
 FormFields but this is not the same as a schema. We have found being  
 able to handle portal_type and schema or fields ie. an instance  
 FormFields() in the super class to avoid repeated use of the somewhat  
 cumbersome FormFields(TextLine(__name__...)) code.
 
  we discuss the generic adding approach, we further discuss what has  
  to
  be considered to be generic.
 
  I'm just not sure that generic is so good. If it's easy to make add-  
  and edit-
  views (probably with convenience classes for CMFish container adding  
  behavior)
  and obvious how to register them, then do you need more framework?  
  At least not
  in CMFCore.
 
 
 Explicit is always better than implicit. This stuff really isn't a lot  
 of work but it provides clarity and helps people understand what's  
 going on and I think this is essential for any framework. Less magic  
 is more power. ;-)

sorry, but implementing something like:

class Addform(AddformBase)

fields = form.Fields(ISchema)

and registering it then like:

browser:page
  for=*
  name=myfactoryname
  class=.foo.Addform
  allowed_interface=Procucts.CMFCore.browser.interfaces.ICMFAddForm
  permission=add.whatever
/

..does not give the newbee more clue on whats going on than write it not
at all.

robert

 
 Charlie
 --
 Charlie Clark
 Helmholtzstr. 20
 Düsseldorf
 D- 40215
 Tel: +49-211-938-5360
 GSM: +49-178-782-6226
 
 
 
 ___
 Zope-CMF maillist  -  Zope-CMF@lists.zope.org
 http://mail.zope.org/mailman/listinfo/zope-cmf
 
 See http://collector.zope.org/CMF for bug reports and feature requests


___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-17 Thread Charlie Clark


Am 17.07.2008 um 13:12 schrieb Robert Niederreiter:


class Addform(AddformBase)

   fields = form.Fields(ISchema)

and registering it then like:

browser:page
 for=*
 name=myfactoryname
 class=.foo.Addform
 allowed_interface=Procucts.CMFCore.browser.interfaces.ICMFAddForm
 permission=add.whatever
/

..does not give the newbee more clue on whats going on than write it  
not

at all.



With respect, I disagree but there are newbies and newbies and YMMV.

Our experience on my current project has been that the configuration  
directives are extremely helpful: our developers have very little  
Python or Zope experience but they are all programmers. It hasn't  
removed typo's and copy and paste errors but it has more than once  
proved invaluable when tracking down errors.


Charlie
--
Charlie Clark
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-938-5360
GSM: +49-178-782-6226



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Charlie Clark


Am 15.07.2008 um 23:38 schrieb Martin Aspeli:

Actually, that's interesting... what purpose does 'initial view'  
serve in a world with add forms?


The same as it ever has - you redirect to the initial view from the  
add form because the add form is actually registered for the container  
(IFolderish object) and the initial view is called because the object  
itself hasn't been used.


Should we re-purpose this slightly to make it provide the add form  
view URL?



No, I think it has to be a separate property.

Charlie
--
Charlie Clark
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-938-5360
GSM: +49-178-782-6226



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Robert Niederreiter

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!).

Re: [Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Robert Niederreiter
Hi,

 So, let me try to summarise what I think we're saying here:
 
   - My type has a form like:
 
 class MyAddForm(CMFBaseAddForm):
  fields = form.Fields(IMyType)
  portal_type = 'My type'
 
   - The base form knows to look at self.factory_name to look up the 
 factory when it does the create() call.
 
   - The base add form implements ICMFAddForm
 
   - I register the form as a normal browser:page /, with the 
 convention that the name is the same as the factory name
 
   - The FTI has an 'addview' property, which by convention is set to 
 string:${folder/absolute_url}/@@add/${portal_type}
 
   - The @@add view looks like
 
 class AddView(BrowserView):
  implements(IPublishTraverse)
 
  def publishTraverse(self, request, name):
  portal_types = getToolByName(self.context, 'portal_types')
  fti = getattr(portal_types, name)
  factory = fti.factory
  addview = getMultiAdapter((self.context, request), ICMFAddForm,
name=factory)
  addview.portal_type = name
  return addview
 
 A few things to note about this:
 
   - The traverser doesn't call the view, it just returns it (the 
 publisher will call it when it needs to)
 
   - We don't look up a default, unnamed add form view. This doesn't make 
 any sense unless we really can generalise all forms; frameworks like 
 Dexterity may have a way to do this and thus may be able to have their 
 own versions of @@add, but I don't think this something we should do at 
 the CMF level.
+/-
i would provide a default add form anyway. consider how archetypes
works. you never write an addform (especially because there are
none :)). for most of the usecases default sequencial add forms fit
quite fine. so for most usecases even the registration for the add form
is lost code lines.

to provide this, the CMFBaseAddForm simply has to provide one more
property.

class CMFBaseAddForm(BrowserView):

@property
def fields(self):
portal_types = getToolByName(self.context, 'portal_types')
fti = getattr(portal_types, self.portal_type)
return form.Fields(fti.schema)

the publishTraverse function of AddView then would do something like:

   ...
   factory = fti.factory
   try:
   addview = getMultiAdapter((self.context, request),
 ICMFAddForm, 
 name=factory)
   except ComponentLookupError, e:
   addview = getMultiAdapter((self.context, request),
 ICMFAddForm, 
 name=u'cmfdefaultadd')
   ...

   - This doesn't require any more registrations than the simple add form 
 browser view.
see above. this registration would be then the first possible
customization step if desired.

 
   - If I don't want to use this idiom, I could change that TALES 
 expression to something like string:${folder/absolute_url}/@@add-my-stuff
 
 I quite like this approach now. ;-)
great :)

 
 Martin

Robert
 
 ___
 Zope-CMF maillist  -  Zope-CMF@lists.zope.org
 http://mail.zope.org/mailman/listinfo/zope-cmf
 
 See http://collector.zope.org/CMF for bug reports and feature requests



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Martin Aspeli
yuppie [EMAIL PROTECTED] writes:
 
  class MyAddForm(CMFBaseAddForm):
  fields = form.Fields(IMyType)
  portal_type = 'My type'
 
 Here you are mixing up content type with portal type. We can't hardcode 
 the portal type if we want to use the add form for renamed/derived 
 portal types as well.

Right, sorry. We probably don't need this at all, actually, if the
traverser sets it along with the factory name.

   - The base form knows to look at self.factory_name to look up the 
  factory when it does the create() call.
 
 create() needs to know the portal type, not just the factory name.

Okay, sure, but that's known at this stage too if the traverser saves it.

 Above you wanted to use self.factory_name inside the form, now you set 
 addview.portal_type.

 We definitely have to pass the portal type to the view. If we have to 
 look up the factory name in publishTraverse, we might want to pass it to 
 the view as well.

Right.

Martin

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Martin Aspeli
Robert Niederreiter [EMAIL PROTECTED] writes:

 +/-
 i would provide a default add form anyway. consider how archetypes
 works.

Not necessarily an example to follow, though, is it. :)

 you never write an addform (especially because there are
 none :)). for most of the usecases default sequencial add forms fit
 quite fine. so for most usecases even the registration for the add form
 is lost code lines.

I'm not so sure about that, because ...
 
 to provide this, the CMFBaseAddForm simply has to provide one more
 property.
 
 class CMFBaseAddForm(BrowserView):
 
 @property
 def fields(self):
 portal_types = getToolByName(self.context, 'portal_types')
 fti = getattr(portal_types, self.portal_type)
 return form.Fields(fti.schema)


Here you assumption is that that schema is saved on and returnable from the FTI.
This is a pretty fundamental change to the way CMF and CMF types work. First of
all, it requires that the FTI can know the schema, which will probably mean
storing the dotted name of the schema somewhere or inferring it from something
else (a class, or the factory - the IFactory interface actually has some support
for this).

Now, I'm not actually against this. Dexterity works in this very manner (it has
a lookup_schema() method that works a bit like the schema property above, and
can source the schema from a number of different places including TTW-only
configuration, a filesystem file or a real filesystem interface via a dotted
name). If some of that could be pushed down to CMF, then of course that'd be
great - less code to be kept in Dexterity. But I'm not sure CMF wants to swallow
that much of an architectural change at this stage.

Also note that defaulting to form.Fields(fti.schema) is probably not enough.
Many forms, at least, will require custom widgets, and settings like groups and
so on. Dexterity has a way for the schema interface to give hints for how it
will be rendered (using tagged values) and a (fairly hairy) algorithm for
including them, but I won't actually recommend that pattern for general purpose
filesystem code (it's necessary for the case where you have pluggable UI that
source schema fields from multiple sources - again something that's probably not
in scope for base CMF).

If we want to be true to the tradition of Zope 3 and its simplified content
types metaphor, then  I think we should assume that a type consists of:

 - a class
 - a schema interface
 - an add form/view
 - an edit form/view

plus the FTI to install it into the CMF site. I wouldn't try to be too clever
and generalise away any of these.

Martin



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Daniel Nouri
Martin Aspeli writes:
 If we want to be true to the tradition of Zope 3 and its simplified content
 types metaphor, then  I think we should assume that a type consists of:

  - a class
  - a schema interface
  - an add form/view
  - an edit form/view

 plus the FTI to install it into the CMF site. I wouldn't try to be too clever
 and generalise away any of these.

+1 to keeping this simple at the CMF level.  Clever libraries can always
hook into form lookup using the mechanics discussed and perform whatever
magic they need.


Daniel

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Robert Niederreiter

Am Mittwoch, den 16.07.2008, 13:04 + schrieb Martin Aspeli:
 Robert Niederreiter [EMAIL PROTECTED] writes:
 
  +/-
  i would provide a default add form anyway. consider how archetypes
  works.
 
 Not necessarily an example to follow, though, is it. :)
 
  you never write an addform (especially because there are
  none :)). for most of the usecases default sequencial add forms fit
  quite fine. so for most usecases even the registration for the add form
  is lost code lines.
 
 I'm not so sure about that, because ...
  
  to provide this, the CMFBaseAddForm simply has to provide one more
  property.
  
  class CMFBaseAddForm(BrowserView):
  
  @property
  def fields(self):
  portal_types = getToolByName(self.context, 'portal_types')
  fti = getattr(portal_types, self.portal_type)
  return form.Fields(fti.schema)
 
 
 Here you assumption is that that schema is saved on and returnable from the 
 FTI.
 This is a pretty fundamental change to the way CMF and CMF types work. First 
 of
 all, it requires that the FTI can know the schema, which will probably mean
 storing the dotted name of the schema somewhere or inferring it from something
 else (a class, or the factory - the IFactory interface actually has some 
 support
 for this).
 
 Now, I'm not actually against this. Dexterity works in this very manner (it 
 has
 a lookup_schema() method that works a bit like the schema property above, and
 can source the schema from a number of different places including TTW-only
 configuration, a filesystem file or a real filesystem interface via a dotted
 name). If some of that could be pushed down to CMF, then of course that'd be
 great - less code to be kept in Dexterity. But I'm not sure CMF wants to 
 swallow
 that much of an architectural change at this stage.
it's not that big architectual change. everything else discussed is
possible anyway. i would rather call it a feature than a design change
(since the change happens anyway).

we discuss the generic adding approach, we further discuss what has to
be considered to be generic.

2 more properties on the fti (addforminterface, schemainterface), both
are optional, but provide then the discussed and requested flexibility
for different type implementations.

if we do not consider this questions at this state, again the result
will be stupid and ugly subclassing and incompatibility and bad readable
code and overrides.zcml (which is one thing i really hate!).

 
 Also note that defaulting to form.Fields(fti.schema) is probably not enough.
 Many forms, at least, will require custom widgets, and settings like groups 
 and
 so on. Dexterity has a way for the schema interface to give hints for how it
 will be rendered (using tagged values) and a (fairly hairy) algorithm for
 including them, but I won't actually recommend that pattern for general 
 purpose
 filesystem code (it's necessary for the case where you have pluggable UI that
 source schema fields from multiple sources - again something that's probably 
 not
 in scope for base CMF).
right, therefor you always have the possibility to write your own form
implementation.

 
 If we want to be true to the tradition of Zope 3 and its simplified content
 types metaphor, then  I think we should assume that a type consists of:
 
  - a class
  - a schema interface
  - an add form/view
  - an edit form/view
 
 plus the FTI to install it into the CMF site. I wouldn't try to be too clever
 and generalise away any of these.
i don't try to generalize, i try to simplify. and i think such default
behaviour is benefit in any way.

i simply wonder why people should write code for default behaviour when
there can be a default implementation.

i only want to point here to the plone portlets engine. why is it
necessary to provide 4 (!) classes, a template and a zcml configuration
for 1 portlet? thats imo too much, especially because people are
familiar with and love the 'write-less-do-more' mentality, and adherence
to a tradition is not automatically more productive or easier to
understand.

Robert

 
 Martin
 
 
 
 ___
 Zope-CMF maillist  -  Zope-CMF@lists.zope.org
 http://mail.zope.org/mailman/listinfo/zope-cmf
 
 See http://collector.zope.org/CMF for bug reports and feature requests


___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Daniel Nouri
Robert Niederreiter writes:
 2 more properties on the fti (addforminterface, schemainterface), both
 are optional, but provide then the discussed and requested flexibility
 for different type implementations.

If you copy a FTI, you can probably reuse the add and edit forms
available for the type you're copying.

If you're using a different schema, you'll write filesystem code anyway.
In which case it's easy enough to register another add and edit form.
This will also avoid redundancy with the proposed addforminterface and
schemainterface FTI properties in the case of custom add and edit forms.
And it'll make it obvious to the developer where to hook in to customize
the default forms.

 if we do not consider this questions at this state, again the result
 will be stupid and ugly subclassing and incompatibility and bad readable
 code and overrides.zcml (which is one thing i really hate!).

As soon as whatever default form that's provided by the framework
doesn't work for you, you're back to stupid and ugly subclassing,
which I don't think has to be stupid and ugly at all.  In fact, I
believe that using subclassing or utility functions in these forms will
lead to more understandable code here.

Where would we need overrides.zcml?


Daniel

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Daniel Nouri
Robert Niederreiter writes:

 Am Mittwoch, den 16.07.2008, 16:24 +0200 schrieb Daniel Nouri:
 Where would we need overrides.zcml?

 in the case where ICMFAddForm is no longer my interface to look up. then
 i have to overwrite the traverser.

Why would ICMFAddForm no longer be the interface to look up?  It's the
the only type of add form that promises to do something meaningful with
the 'portal_type' attribute that's set on it in the traverser.


Daniel
___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Martin Aspeli

 it's not that big architectual change. everything else discussed is
 possible anyway. i would rather call it a feature than a design change
 (since the change happens anyway).

I think it's a fairly big shift to assume that the FTI has knowledge of the
schema of the type. It's not necessarily a *bad* idea (at least I don't think
so, since this is basically how Dexterity works :-), but right now, FTI doesn't
have any notion of a schema. With this change, you're effectively dictating (or
strongly suggesting) that all CMF types have a schema and that this is the
basis for forms, and suggesting that forms aren't registered as independent
views but rather inferred from this schema.

 we discuss the generic adding approach, we further discuss what has to
 be considered to be generic.

I'm just not sure that generic is so good. If it's easy to make add- and edit-
views (probably with convenience classes for CMFish container adding behavior)
and obvious how to register them, then do you need more framework? At least not
in CMFCore.

Better to leave that up to higher level frameworks to implement this type of
generality.

 2 more properties on the fti (addforminterface, schemainterface), both
 are optional, but provide then the discussed and requested flexibility
 for different type implementations.

Optional properties still need to be maintained and may still create confusion
or conflicting assumptions. Here, we've invented two new concepts (the type has
a schema, the type has an interface that describes the add form). It may be that
more advanced frameworks need something a bit different, and so they'll have to
either overload or ignore those properties.

 if we do not consider this questions at this state, again the result
 will be stupid and ugly subclassing and incompatibility and bad readable
 code and overrides.zcml (which is one thing i really hate!).

I don't know if that's true. Trying to solve all problems at the most basic
level is probably not a good idea. Giving the right hooks probably is.

I think if we make the addview name used for the rendering of menus a TALES
expression, then the traverser thing becomes a CMFDefault implementation detail
(not even CMFCore).

Dexterity has its own FTI type. It will always need that, no matter how many
hooks you have here. I have no problem with that, actually - GenericSetup makes
it easy. Dexterity does not need any overrides.zcml either. ;-)

 right, therefor you always have the possibility to write your own form
 implementation.

I think it's a mark of bad framework design if that possibility really means
throwing away most of the conventions and standard support and building up
something else starting from a very low level. In that case, the framework's
tried to too much application-level work that ends up being useless to the
actual applications (like Plone), who then have to invent their own parallel
framework to support their own slightly divergent use cases.

 i simply wonder why people should write code for default behaviour when
 there can be a default implementation.

I don't think it's a safe assumption that *at the CMFCore level* we'll have a
sensible default. It's a pretty big assumption that it's sensible for most
applications to have a linear form that uses formlib's default widgets with no
custom setup code for most types.

 i only want to point here to the plone portlets engine. why is it
 necessary to provide 4 (!) classes, a template and a zcml configuration
 for 1 portlet? thats imo too much, especially because people are
 familiar with and love the 'write-less-do-more' mentality, and adherence
 to a tradition is not automatically more productive or easier to
 understand.

I can tell you why it's necessary in another thread. It's irrelevant here (and
on this list).

Martin

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Wichert Akkerman
Previously Martin Aspeli wrote:
 
  it's not that big architectual change. everything else discussed is
  possible anyway. i would rather call it a feature than a design change
  (since the change happens anyway).
 
 I think it's a fairly big shift to assume that the FTI has knowledge of the
 schema of the type. It's not necessarily a *bad* idea (at least I don't think
 so, since this is basically how Dexterity works :-), but right now,
 FTI doesn't have any notion of a schema. With this change, you're
 effectively dictating (or strongly suggesting) that all CMF types have
 a schema and that this is the basis for forms, and suggesting that
 forms aren't registered as independent views but rather inferred from
 this schema.

Possibly related: I have often had a desire to be able to annotate or
extend the FTI. In Plone (and to a lesser degree CMF) we have lots of
settings that change a portal type's behaviour that are stored in
various places: versioning settings, markup configuration, workflow
chains, etc.

I suppose there is no reason not to use annotations on the FTI right
now; perhaps we should investigate migrating some things in that
direction.

Wichert.

-- 
Wichert Akkerman [EMAIL PROTECTED]It is simple to make things.
http://www.wiggy.net/   It is hard to make things simple.
___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Martin Aspeli
Wichert Akkerman [EMAIL PROTECTED] writes:

 Possibly related: I have often had a desire to be able to annotate or
 extend the FTI. In Plone (and to a lesser degree CMF) we have lots of
 settings that change a portal type's behaviour that are stored in
 various places: versioning settings, markup configuration, workflow
 chains, etc.

I agree that this is important. The FTI is a natural place to store persistent
information about a type, and this pattern is possibly a bit under-appreciated
as we try to use individual local components for type-specific stuff.

Dexterity subclasses the standard FTI to add a few more properties, which is
nice because you get some TTW configurability for free. Using different FTI
types is relatively non-problematic when we use GS for installation.

I think this is slightly off-topic in this thread, though. :)

Martin

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Martin Aspeli
Daniel Nouri [EMAIL PROTECTED] writes:

 
 Robert Niederreiter writes:
 
  Am Mittwoch, den 16.07.2008, 16:24 +0200 schrieb Daniel Nouri:
  Where would we need overrides.zcml?
 
  in the case where ICMFAddForm is no longer my interface to look up. then
  i have to overwrite the traverser.
 
 Why would ICMFAddForm no longer be the interface to look up?  It's the
 the only type of add form that promises to do something meaningful with
 the 'portal_type' attribute that's set on it in the traverser.

And even if it weren't - we shouldn't hardcode the traversal adapter. We should
make this a convenient implementation option. The actual URL of the add view
should configurable via a TALES expression, which means that it can be written
without the @@add bit.

Martin

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-16 Thread Daniel Nouri
Martin Aspeli writes:

 Daniel Nouri [EMAIL PROTECTED] writes:

 
 Robert Niederreiter writes:
 
  Am Mittwoch, den 16.07.2008, 16:24 +0200 schrieb Daniel Nouri:
  Where would we need overrides.zcml?
 
  in the case where ICMFAddForm is no longer my interface to look up. then
  i have to overwrite the traverser.
 
 Why would ICMFAddForm no longer be the interface to look up?  It's the
 the only type of add form that promises to do something meaningful with
 the 'portal_type' attribute that's set on it in the traverser.

 And even if it weren't - we shouldn't hardcode the traversal
 adapter. We should make this a convenient implementation option. The
 actual URL of the add view should configurable via a TALES expression,
 which means that it can be written without the @@add bit.

A convenient implementation option that the CMF types will need to use:
Their forms will need to depend on the @@add bit to tell them about the
portal_type.  Otherwise, if you make a copy of one of those types,
you'll end up with a form for them that creates objects of the original
type.

  class ICMFAddForm(Interface):
  portal_type = Attribute(Name of portal_type that I'm to create)

  def __call__():
  Returns HTML

This should be enough as a contract for our little forms, right?


Daniel

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Robert Niederreiter
hi martin,

Am Montag, den 14.07.2008, 21:31 +0100 schrieb Martin Aspeli:
 Hi Robert,
 
  
  maybe it's a little late to join this discussion. i read the thread and
  want to point some of my thoughts here.
  
  imo its a bad idea to depend on static zcml configuration for factory
  types. martin did a nice approach in his portlets engine with a name
  traverser when calling a generic adding view. 
 
 I'm not quite sure I follow here. The portlets machinery just looks up 
 the add view in a utility that stores its name, and then invokes it. 
 There's a custom analog to IAdding called +portlet to keep the 
 namespace separate.

you post i.e. /++contextportlets++plone.rightcolumn/+/portlets.Login as
action for adding a portlet and let your ITraversable implementations
perform what to do in plone.app.portlets.browser.traversal.py.

thats imo a nice approach

 
  i took this idea and the
  adding mechanism of devilstick works this way as well and depends on the
  fti too. so a call of foo/add/portal_type returns an add view for
  requested type.
 
 How's that different to foo/+/factory-name ?

not that much. i only wanted to say that there might be no need to
register a seperate addview/form for every portal type. having the type
name it should be possible to get the schema interface of the requested
type, so it's possible to provide a generic addview/form.

this interface lookup, and addview/form instanciation might be done then
in a traverser, that's the most 'zopeish' solution imo.

 
  doing it this way would even work if someone renames a
  portal_type for some reason without the needs to modify or overwrite any
  existing zcml, because the traverser simply tries to read the fti of
  ``portal_type``.
 
 Mmm right. Local components work here too, of course.
 
  to make custom add views available there could be a new attribute in the
  fti which contains the name of a custom add view to look up. the
  traverser could then first lookup if a custom add view was set (this has
  to be configured static with zcml anyway) and looks it up by its name or
  returns the default add view. as an alternative this could also be done
  by aliases.
 
 I'm not sure you need the traverser, though, if you have a standard way 
 to generate the list of URLs for the add view, but maybe I'm missing 
 something?
 
  im not sure if it is desirable to alter the IAdding mechanism with
  something like a simple view. at least i see no reason for implementing
  'yet another adding mechanism'.
 
 Having the add view be a view for a view (i.e. the context of the real 
 add view is not a content object) is sometimes quite painful.

until someone got the clue :). yes you're right here, constructs like
``aq_inner(self.context.context)`` and similar simply look ugly. but on
the other hand, if you kick this construct, you have to provide another
mechanism which is responsible to finally add what has to be added. if
this is more elegant then...?

 
  in the end a quick question. isn't the portal_factory itself obsolete if
  a clean adding mechanism is working then and the only thing to maintain
  further the fti stuff?
 
 Plone's portal_factory has nothing to do with this, but yes, we want to 
 rip the damned thing out.

great

 
 Martin

robert


___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Martin Aspeli

Hi Robert,


imo its a bad idea to depend on static zcml configuration for factory
types. martin did a nice approach in his portlets engine with a name
traverser when calling a generic adding view. 
I'm not quite sure I follow here. The portlets machinery just looks up 
the add view in a utility that stores its name, and then invokes it. 
There's a custom analog to IAdding called +portlet to keep the 
namespace separate.


you post i.e. /++contextportlets++plone.rightcolumn/+/portlets.Login as
action for adding a portlet and let your ITraversable implementations
perform what to do in plone.app.portlets.browser.traversal.py.

thats imo a nice approach


Ah, I get you. Actually, the ++contextportlets++plone.rightcolumn bit is 
a namespace traversal adapter that addresses a particular portlet 
manager (which is basically an ordered container); + is an IAdding view 
(actually, an IPortletAdding view) registered for the portlet manager 
container. portlets.Login is the name of the add view for a particular 
portlet.


So, this approach is identical to (and borrowed from) the old Zope 
3/ZMI approach that you have an add view that is a statically registered 
view for IAdding. The adding view is *not* generic. Each portlet 
registers its own add view. We have a formlib-based base class though.


Now, I think this is fine for portlets, since it's relatively easy to 
register this add view (there's a single ZCML directive to register all 
portlet-related information), and portlets are not like portal types 
(there's no persistent FTI that can be cloned).



i took this idea and the
adding mechanism of devilstick works this way as well and depends on the
fti too. so a call of foo/add/portal_type returns an add view for
requested type.

How's that different to foo/+/factory-name ?


not that much. i only wanted to say that there might be no need to
register a seperate addview/form for every portal type. having the type
name it should be possible to get the schema interface of the requested
type, so it's possible to provide a generic addview/form.


Right. That's probably a reasonable default (and is, in effect, what 
Dexterity does as well, although it registers add views as local adapter 
factories that know their portal_type).



this interface lookup, and addview/form instanciation might be done then
in a traverser, that's the most 'zopeish' solution imo.


This is quite an interesting approach, actually. After traversal, what 
is self.context in the add form? Is it the form, or the 'addview' 
traverser thing?


Having the add view be a view for a view (i.e. the context of the real 
add view is not a content object) is sometimes quite painful.


until someone got the clue :). yes you're right here, constructs like
``aq_inner(self.context.context)`` and similar simply look ugly. but on
the other hand, if you kick this construct, you have to provide another
mechanism which is responsible to finally add what has to be added. if
this is more elegant then...?


The final 'add' operation can be done by a base class for the view. 
That's how Yuppie's formlib thing works, and how z3c.form prefers to work.


self.context.context can be majorly painful, though. For example, look 
at 
http://dev.plone.org/plone/browser/plone.app.vocabularies/trunk/plone/app/vocabularies/workflow.py.


Here, we need to acquire something, but since the context may be the 
IAdding view, we have to do this everywhere:


 context = getattr(context, 'context', context)

Yuck!

Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Charlie Clark


Am 14.07.2008 um 12:37 schrieb yuppie:

Add links are just special 'actions', they should be integrated with  
CMF's action machinery. Based on the information in the type infos  
we should be able to create normal IActionInfo objects. (IActionInfo  
defines the non-persistent wrapper around actions, today we would  
use adapters to implement this.)


If we don't want to use a convention, we need a new property. And if  
we want to be flexible enough to add the portal type name to the  
query, a TALES expression for the URL wouldn't be overkill.



Works for me - would this be something like the initial view for  
types?


Charlie
--
Charlie Clark
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-938-5360
GSM: +49-178-782-6226



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Charlie Clark


Am 14.07.2008 um 12:17 schrieb yuppie:

CMF 2.1 was released with some formlib based edit forms. I don't  
think it was a mistake, because at that time z3c.form wasn't  
available in the Zope 2 world.


It certainly wasn't a mistake in fact I think it was great. To me it  
seems reasonable at least to try and complete a set of browser views  
using zope.formlib for CMF 2.2.


We're already using zope.formlib in the experimental browser  
views  edit forms. The reference to a sinking ship is totally off- 
target. My  own view is that sometimes it is better to wait for  
version 2 of a  product or library to be released before adoption.  
Surely Plone has  suffered from adopting some stuff too early?

*shrug*
Do what you please. I'm not particularly wedded to one or the  
other. But having used both, I'm pretty sure that z3c.form is a  
better library. In many ways, z3c.form *is* version 2 of formlib.


Exactly. z3c.form is a new version of zope.formlib that doesn't care  
about backwards compatibility. All development is done in z3c.form.  
Using the picture of a sinking ship: At least the crew has already  
abandoned the formlib ship. And without crew it will sink sooner or  
later.


I really don't think the ship metaphor is appropriate - software tends  
to be around for a lot longer than you expect (hasn't MS only just  
stopped support for Window 3.11?) but that is probably irrelevant. The  
questions are probably: do we have any problems with zope.formlib that  
we know will be solved by using z3c.form? what is the overhead of  
migrating between the two? So far I'm just really a consumer of the  
formlib integration in the CMF. I had a brief look at the z3c.form  
stuff last night  and it didn't seem to be radically different from  
formlib so that a migration shouldn't be too much work. But perhaps  
for precisely the same reason there is less of a need to migrate. It  
would certainly be advantageous to have both five.formlib and  
five.form and it's great that we can expect to have a common basis for  
the CMF and Plone.


It was always a goal of CMF to minimize dependencies. But Zope  
became less monolithic, so we have to define the Zope dependency  
ourselves. It's no longer just the Zope 2 distribution, we have to  
use separately shipped packages like five.localsitemanager as well.  
And z3c.form is *the* current Zope package for creating forms.



You've hit on an important point: Zope 2.10 and Zope 2.11 both ship  
with zope.formlib but things like sitemanager are changing the game  
and will require more package support so why not bite the bullet?


Charlie
--
Charlie Clark
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-938-5360
GSM: +49-178-782-6226



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Robert Niederreiter
Hi,

Am Dienstag, den 15.07.2008, 08:53 +0100 schrieb Martin Aspeli:
 Hi Robert,
 
  imo its a bad idea to depend on static zcml configuration for factory
  types. martin did a nice approach in his portlets engine with a name
  traverser when calling a generic adding view. 
  I'm not quite sure I follow here. The portlets machinery just looks up 
  the add view in a utility that stores its name, and then invokes it. 
  There's a custom analog to IAdding called +portlet to keep the 
  namespace separate.
  
  you post i.e. /++contextportlets++plone.rightcolumn/+/portlets.Login as
  action for adding a portlet and let your ITraversable implementations
  perform what to do in plone.app.portlets.browser.traversal.py.
  
  thats imo a nice approach
 
 Ah, I get you. Actually, the ++contextportlets++plone.rightcolumn bit is 
 a namespace traversal adapter that addresses a particular portlet 
 manager (which is basically an ordered container); + is an IAdding view 
 (actually, an IPortletAdding view) registered for the portlet manager 
 container. portlets.Login is the name of the add view for a particular 
 portlet.
 
 So, this approach is identical to (and borrowed from) the old Zope 
 3/ZMI approach that you have an add view that is a statically registered 
 view for IAdding. The adding view is *not* generic. Each portlet 
 registers its own add view. We have a formlib-based base class though.

i know, but the fact that portlets have it's own add view has nothing to
do with the fact that the traverser is responsible for the magic.

 
 Now, I think this is fine for portlets, since it's relatively easy to 
 register this add view (there's a single ZCML directive to register all 
 portlet-related information), and portlets are not like portal types 
 (there's no persistent FTI that can be cloned).
 
  i took this idea and the
  adding mechanism of devilstick works this way as well and depends on the
  fti too. so a call of foo/add/portal_type returns an add view for
  requested type.
  How's that different to foo/+/factory-name ?
  
  not that much. i only wanted to say that there might be no need to
  register a seperate addview/form for every portal type. having the type
  name it should be possible to get the schema interface of the requested
  type, so it's possible to provide a generic addview/form.
 
 Right. That's probably a reasonable default (and is, in effect, what 
 Dexterity does as well, although it registers add views as local adapter 
 factories that know their portal_type).
 
  this interface lookup, and addview/form instanciation might be done then
  in a traverser, that's the most 'zopeish' solution imo.
 
 This is quite an interesting approach, actually. After traversal, what 
 is self.context in the add form? Is it the form, or the 'addview' 
 traverser thing?

depends on what your traverser returns :).

consider such an url and the default formlib behaviour:

foo/+/Folder

'+' is the IAdding implementation, which is actually nothing else than a
'factory', but without creating anything like the old behaviour of the
portal_factory.

now it's possible to register an IPublishTraverse implementation for
this specific IAdding implementation (could also be anything else than
IAdding if you want to get rid of it). this traverser then does the FTI
lookup, the schema interface lookup und creates and returns the addform.

in this step you can modify the context of addform as needed.

here is how its done in devilstick:
http://dev.plone.org/collective/browser/devilstick/devilstick.browser/trunk/devilstick/browser/traversal.py
line 71+

so, to follow your intention, there would be some browserpage altering
the factory.

for this factory then an IPublishTraverse implementation is registered.

inside the traverser you can do something like

context = aq_inner(self.context.context)
form = getMultiAdapter((context, self.request),
   IMyFancyAddFormWithoutIAdding,
   name='whatever')
return form.__of__(context)

this ensures the right context in the right acquisition chain.

 
  Having the add view be a view for a view (i.e. the context of the real 
  add view is not a content object) is sometimes quite painful.
  
  until someone got the clue :). yes you're right here, constructs like
  ``aq_inner(self.context.context)`` and similar simply look ugly. but on
  the other hand, if you kick this construct, you have to provide another
  mechanism which is responsible to finally add what has to be added. if
  this is more elegant then...?
 
 The final 'add' operation can be done by a base class for the view. 
 That's how Yuppie's formlib thing works, and how z3c.form prefers to work.
 
 self.context.context can be majorly painful, though. For example, look 
 at 
 http://dev.plone.org/plone/browser/plone.app.vocabularies/trunk/plone/app/vocabularies/workflow.py.
 
 Here, we need to acquire something, but since the context may be the 
 IAdding view, we have to do this 

Re: [Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Robert Niederreiter

Am Dienstag, den 15.07.2008, 12:43 +0200 schrieb yuppie:
 Robert Niederreiter wrote:
  i took this idea and the
  adding mechanism of devilstick works this way as well and depends on the
  fti too. so a call of foo/add/portal_type returns an add view for
  requested type.
  How's that different to foo/+/factory-name ?
  not that much. i only wanted to say that there might be no need to
  register a seperate addview/form for every portal type. having the type
  name it should be possible to get the schema interface of the requested
  type, so it's possible to provide a generic addview/form.
  Right. That's probably a reasonable default (and is, in effect, what 
  Dexterity does as well, although it registers add views as local adapter 
  factories that know their portal_type).
 
  this interface lookup, and addview/form instanciation might be done then
  in a traverser, that's the most 'zopeish' solution imo.
  This is quite an interesting approach, actually. After traversal, what 
  is self.context in the add form? Is it the form, or the 'addview' 
  traverser thing?
  
  depends on what your traverser returns :).
  
  consider such an url and the default formlib behaviour:
  
  foo/+/Folder
  
  '+' is the IAdding implementation, which is actually nothing else than a
  'factory', but without creating anything like the old behaviour of the
  portal_factory.
  
  now it's possible to register an IPublishTraverse implementation for
  this specific IAdding implementation (could also be anything else than
  IAdding if you want to get rid of it). this traverser then does the FTI
  lookup, the schema interface lookup und creates and returns the addform.
  
  in this step you can modify the context of addform as needed.
  
  here is how its done in devilstick:
  http://dev.plone.org/collective/browser/devilstick/devilstick.browser/trunk/devilstick/browser/traversal.py
  line 71+
 
 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.

 
 Would anyone volunteer to implement this (including unit tests) if we 
 decide to choose that approach?
 
 Cheers, Yuppie

robert

 
 
 ___
 Zope-CMF maillist  -  Zope-CMF@lists.zope.org
 http://mail.zope.org/mailman/listinfo/zope-cmf
 
 See http://collector.zope.org/CMF for bug reports and feature requests

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-15 Thread yuppie

Hi Martin!


Martin Aspeli wrote:

CMF trunk uses events instead of _finishConstruction.
Ah, nice. Do you think it'd be feasible to backport this, i.e. copy 
the event handler somewhere in Plone so long as Plone's still using 
an older version of CMF? Or does the new event handler rely on other 
changes to CMF as well?


The changes in handleContentishEvent are simple. The tricky part is to 
make sure notifyWorkflowCreated and indexObject aren't called twice if 
the types tool is used for creating content.


How did you?


Well. First I declared all existing oldstyle factories broken because 
they send the events at the wrong moment. And second, I ripped out 
_finishConstruction. I hope that's acceptable for a new feature release, 
but nothing I would introduce on a maintenance branch.


See http://svn.zope.org/?view=revrev=82763 and 
http://svn.zope.org/?view=revrev=85506 for details.


If you want to backport this to CMF 2.1, I'd try to register the new 
handler for an interface that's only used by your new content classes. 
If you don't touch the types tool, you also have to make sure that your 
new content is never created by the types tool.


If we don't want to use a convention, we need a new property. And if 
we want to be flexible enough to add the portal type name to the 
query, a TALES expression for the URL wouldn't be overkill.


So, a single new property that contains TALES? Called 'addview'?


Let's first see how we decide on Robert's proposal.


Cheers,

Yuppie

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-15 Thread yuppie

Robert Niederreiter wrote:
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.


Writing generic code is just the first step. Pushing this down the stack 
and making it the default pattern for Zope is much harder.


Cheers, Yuppie

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Daniel Nouri
Robert Niederreiter writes:

 Am Dienstag, den 15.07.2008, 12:43 +0200 schrieb yuppie:
 Robert Niederreiter wrote:
  i took this idea and the
  adding mechanism of devilstick works this way as well and depends on 
  the
  fti too. so a call of foo/add/portal_type returns an add view for
  requested type.
  How's that different to foo/+/factory-name ?
  not that much. i only wanted to say that there might be no need to
  register a seperate addview/form for every portal type. having the type
  name it should be possible to get the schema interface of the requested
  type, so it's possible to provide a generic addview/form.
  Right. That's probably a reasonable default (and is, in effect, what 
  Dexterity does as well, although it registers add views as local adapter 
  factories that know their portal_type).
 
  this interface lookup, and addview/form instanciation might be done then
  in a traverser, that's the most 'zopeish' solution imo.
  This is quite an interesting approach, actually. After traversal, what 
  is self.context in the add form? Is it the form, or the 'addview' 
  traverser thing?
  
  depends on what your traverser returns :).
  
  consider such an url and the default formlib behaviour:
  
  foo/+/Folder
  
  '+' is the IAdding implementation, which is actually nothing else than a
  'factory', but without creating anything like the old behaviour of the
  portal_factory.
  
  now it's possible to register an IPublishTraverse implementation for
  this specific IAdding implementation (could also be anything else than
  IAdding if you want to get rid of it). this traverser then does the FTI
  lookup, the schema interface lookup und creates and returns the addform.
  
  in this step you can modify the context of addform as needed.
  
  here is how its done in devilstick:
  http://dev.plone.org/collective/browser/devilstick/devilstick.browser/trunk/devilstick/browser/traversal.py
  line 71+
 
 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')

We could even leave 'factoryNameFromFti' empty by default.

I like this approach!


Daniel

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Daniel Nouri
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.

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?


Daniel

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Martin Aspeli

yuppie wrote:

Robert Niederreiter wrote:
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.


Writing generic code is just the first step. Pushing this down the stack 
and making it the default pattern for Zope is much harder.


We may not have to, though... In Zope 3, there either:

 - is no pattern, everyone does it their own way; or
 - everyone uses IAdding views; and/or
 - everyone uses Zope 3 browser menus via ZCML

This would all be feasible for CMF except that we want to support a 
single content type instantiated as multiple (persistent) portal types, 
all of which are likely to (but may not) share a single view.


I'm still on the fence as to whether I like Robert's proposal. However, 
if we let 'addview' be a TALES property, then I think with his proposal 
it'd look like:


 string:${folder/absolute_url}/@@add/mytype

This would basically allow a default add view to be written that could 
work on all types (provided there was a way to look up the schema of 
that type, which there may not be in plain CMF). The view @@add would be 
a view providing IPublishTraverse. It'd have:


 def publicTraverse(self, request, name):
 portal_type = name
 return GenericAddView(self.context, request, portal_type)

GenericAddView could then be a form that took portal_type as a parameter 
and rendered an add form that knew how to configure and add this type.


This would of course just be one option - if I had a more conventional 
custom add form, I could do:


 string:${folder/absolute_url}/@@my-add-view

or whatever.

Note that we're now getting into the territory that plone.dexterity 
(which, by the way, aims to work with plain CMF as well) covers. It has 
a way for the FTI to broadcast its schema (and that schema can come from 
a number of places, including a filesystem interface, an XML file or 
some TTW configuration). It then has generic add- and edit- forms that 
look up this schema and render the relevant forms.


If we envisage that every plain type in CMF will have a custom add 
view registered as a regular view with a unique class (probably a good 
thing), then I think the @@add/portal_type pattern is overkill. It's 
easier just to let the FTI represent the URL to the view, and for the 
menu code that lets the user pick something to add, to loop over the 
FTIs of addable types and render each link in turn.


Martin


--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-15 Thread 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.

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?


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. 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.


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.


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.


Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-15 Thread Martin Aspeli

Charlie Clark wrote:

Am 14.07.2008 um 12:37 schrieb yuppie:

Add links are just special 'actions', they should be integrated with  
CMF's action machinery. Based on the information in the type infos  
we should be able to create normal IActionInfo objects. (IActionInfo  
defines the non-persistent wrapper around actions, today we would  
use adapters to implement this.)


If we don't want to use a convention, we need a new property. And if  
we want to be flexible enough to add the portal type name to the  
query, a TALES expression for the URL wouldn't be overkill.



Works for me - would this be something like the initial view for  
types?


Actually, that's interesting... what purpose does 'initial view' serve 
in a world with add forms?


Should we re-purpose this slightly to make it provide the add form view URL?

Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-14 Thread Robert Niederreiter
Hi,

maybe it's a little late to join this discussion. i read the thread and
want to point some of my thoughts here.

imo its a bad idea to depend on static zcml configuration for factory
types. martin did a nice approach in his portlets engine with a name
traverser when calling a generic adding view. i took this idea and the
adding mechanism of devilstick works this way as well and depends on the
fti too. so a call of foo/add/portal_type returns an add view for
requested type. doing it this way would even work if someone renames a
portal_type for some reason without the needs to modify or overwrite any
existing zcml, because the traverser simply tries to read the fti of
``portal_type``.

to make custom add views available there could be a new attribute in the
fti which contains the name of a custom add view to look up. the
traverser could then first lookup if a custom add view was set (this has
to be configured static with zcml anyway) and looks it up by its name or
returns the default add view. as an alternative this could also be done
by aliases.

im not sure if it is desirable to alter the IAdding mechanism with
something like a simple view. at least i see no reason for implementing
'yet another adding mechanism'.

in the end a quick question. isn't the portal_factory itself obsolete if
a clean adding mechanism is working then and the only thing to maintain
further the fti stuff?

i did not studied z3c.form yet, so no statement to this from my side.

regards

robert

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-14 Thread yuppie

Hi!


Martin Aspeli wrote:

Charlie Clark wrote:

Am 13.07.2008 um 20:21 schrieb Martin Aspeli:
Thus, if CMF hasn't yet picked a form library in a release, then you  
could try to learn from Plone's mistakes and not jump on a sinking  
ship. :)


CMF 2.1 was released with some formlib based edit forms. I don't think 
it was a mistake, because at that time z3c.form wasn't available in the 
Zope 2 world.


We're already using zope.formlib in the experimental browser views  
edit forms. The reference to a sinking ship is totally off-target. My  
own view is that sometimes it is better to wait for version 2 of a  
product or library to be released before adoption. Surely Plone has  
suffered from adopting some stuff too early?


*shrug*

Do what you please. I'm not particularly wedded to one or the other. But 
having used both, I'm pretty sure that z3c.form is a better library. In 
many ways, z3c.form *is* version 2 of formlib.


Exactly. z3c.form is a new version of zope.formlib that doesn't care 
about backwards compatibility. All development is done in z3c.form. 
Using the picture of a sinking ship: At least the crew has already 
abandoned the formlib ship. And without crew it will sink sooner or later.


It was always a goal of CMF to minimize dependencies. But Zope became 
less monolithic, so we have to define the Zope dependency ourselves. 
It's no longer just the Zope 2 distribution, we have to use separately 
shipped packages like five.localsitemanager as well. And z3c.form is 
*the* current Zope package for creating forms.



Cheers,

Yuppie

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-14 Thread yuppie

Hi Martin!


Martin Aspeli wrote:

# check preconditions
checkObject(container, name, content)


I doubt constraints based on __setitem__ and __parent__ work in Zope 2.


Well, they do in the sense that if you have them and we have this code, 
we'll get an exception. They don't work generally, tough, so this may be 
YAGNI. It was copied from Five's Adding implementation, so I figured it 
should be kept if someone's relying on it.


That's quite hypothetical. If someone figures out how to use this for 
stuff like the allowType check, it's useful. If not, it is YAGNI.


In case of doubt, I prefer to remove code like that and to wait until 
someone complains.



content.id = name
container._setObject(name, content)
content = container._getOb(name)
if fti is not None:
fti._finishConstruction(content)


CMF trunk uses events instead of _finishConstruction.


Ah, nice. Do you think it'd be feasible to backport this, i.e. copy the 
event handler somewhere in Plone so long as Plone's still using an older 
version of CMF? Or does the new event handler rely on other changes to 
CMF as well?


The changes in handleContentishEvent are simple. The tricky part is to 
make sure notifyWorkflowCreated and indexObject aren't called twice if 
the types tool is used for creating content.


BTW: plone.z3cform's AddForm doesn't include a create method, so I can't 
see your complete create-and-add procedure. You might want to compare 
your code with the ContentAddFormBase of CMFDefault trunk:

http://svn.zope.org/Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py?rev=86225view=auto


We could make this overrideable as well, with another FTI property.


I guess I'd rather have a flexible explicit URL than an implicit URL 
ruled by convention.


Agree. So does this mean we want a separate property for the add view 
name? Should it be a simple string or a TALES thing?


Add links are just special 'actions', they should be integrated with 
CMF's action machinery. Based on the information in the type infos we 
should be able to create normal IActionInfo objects. (IActionInfo 
defines the non-persistent wrapper around actions, today we would use 
adapters to implement this.)


If we don't want to use a convention, we need a new property. And if we 
want to be flexible enough to add the portal type name to the query, a 
TALES expression for the URL wouldn't be overkill.



Cheers,

Yuppie

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-14 Thread yuppie

Daniel Nouri wrote:

I just relicensed and moved plone.z3cform to the Zope repository:

  http://svn.zope.org/plone.z3cform/trunk/


Great! Yuppie

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-14 Thread Martin Aspeli

Hi Yuppie,



I doubt constraints based on __setitem__ and __parent__ work in Zope 2.
Well, they do in the sense that if you have them and we have this code, 
we'll get an exception. They don't work generally, tough, so this may be 
YAGNI. It was copied from Five's Adding implementation, so I figured it 
should be kept if someone's relying on it.


That's quite hypothetical. If someone figures out how to use this for 
stuff like the allowType check, it's useful. If not, it is YAGNI.


In case of doubt, I prefer to remove code like that and to wait until 
someone complains.


I have no problem with doing that.


content.id = name
container._setObject(name, content)
content = container._getOb(name)
if fti is not None:
fti._finishConstruction(content)

CMF trunk uses events instead of _finishConstruction.
Ah, nice. Do you think it'd be feasible to backport this, i.e. copy the 
event handler somewhere in Plone so long as Plone's still using an older 
version of CMF? Or does the new event handler rely on other changes to 
CMF as well?


The changes in handleContentishEvent are simple. The tricky part is to 
make sure notifyWorkflowCreated and indexObject aren't called twice if 
the types tool is used for creating content.


How did you?

BTW: plone.z3cform's AddForm doesn't include a create method, so I can't 
see your complete create-and-add procedure.


The idea is that the concrete add view implements this method. I'm not 
sure it's desirable to completely generalise this, but maybe a default 
implementation would be useful.


You might want to compare 
your code with the ContentAddFormBase of CMFDefault trunk:

http://svn.zope.org/Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py?rev=86225view=auto


Will do!


We could make this overrideable as well, with another FTI property.
I guess I'd rather have a flexible explicit URL than an implicit URL 
ruled by convention.
Agree. So does this mean we want a separate property for the add view 
name? Should it be a simple string or a TALES thing?


Add links are just special 'actions', they should be integrated with 
CMF's action machinery. Based on the information in the type infos we 
should be able to create normal IActionInfo objects. (IActionInfo 
defines the non-persistent wrapper around actions, today we would use 
adapters to implement this.)


If we don't want to use a convention, we need a new property. And if we 
want to be flexible enough to add the portal type name to the query, a 
TALES expression for the URL wouldn't be overkill.


So, a single new property that contains TALES? Called 'addview'?

I can get with that. ;-)

Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-14 Thread Martin Aspeli

Hi Robert,



maybe it's a little late to join this discussion. i read the thread and
want to point some of my thoughts here.

imo its a bad idea to depend on static zcml configuration for factory
types. martin did a nice approach in his portlets engine with a name
traverser when calling a generic adding view. 


I'm not quite sure I follow here. The portlets machinery just looks up 
the add view in a utility that stores its name, and then invokes it. 
There's a custom analog to IAdding called +portlet to keep the 
namespace separate.



i took this idea and the
adding mechanism of devilstick works this way as well and depends on the
fti too. so a call of foo/add/portal_type returns an add view for
requested type.


How's that different to foo/+/factory-name ?


doing it this way would even work if someone renames a
portal_type for some reason without the needs to modify or overwrite any
existing zcml, because the traverser simply tries to read the fti of
``portal_type``.


Mmm right. Local components work here too, of course.


to make custom add views available there could be a new attribute in the
fti which contains the name of a custom add view to look up. the
traverser could then first lookup if a custom add view was set (this has
to be configured static with zcml anyway) and looks it up by its name or
returns the default add view. as an alternative this could also be done
by aliases.


I'm not sure you need the traverser, though, if you have a standard way 
to generate the list of URLs for the add view, but maybe I'm missing 
something?



im not sure if it is desirable to alter the IAdding mechanism with
something like a simple view. at least i see no reason for implementing
'yet another adding mechanism'.


Having the add view be a view for a view (i.e. the context of the real 
add view is not a content object) is sometimes quite painful.



in the end a quick question. isn't the portal_factory itself obsolete if
a clean adding mechanism is working then and the only thing to maintain
further the fti stuff?


Plone's portal_factory has nothing to do with this, but yes, we want to 
rip the damned thing out.


Martin

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Martin Aspeli

Hi Yuppie,


Martin Aspeli wrote:
I see that Yuppie has been experimenting with add forms. From what I can 
tell, he's using a custom formlib base class and registering views as 
e.g. addFile.html. It also look as if he's registering that view as an 
action in portal_actions, in the 'folder' category.


That's correct. But I have to mention that not all parts of these 
changes have reached the same stage of maturation. Using 'folder' 
category Actions is a temporary hack to generate menu items for the new 
add forms. I'm glad you want to help to find a better solution.


Ah, good.

Plone currently supports add forms for the IAdding (+) view in a 
somewhat ugly way (it looks to see if there's a view for IAdding with 
the same name as the 'factory' set in the FTI of an addable type, and if 
so, provides a link to it). IAdding can be a bit painful, so we're 
interested in supporting an approach based on simple views.


Good.

It's also worth noting that z3c.form (via plone.z3cform, which should be 
plain CMF compatible, though you may want a different default template) 
has support for such views in quite a generic way. The CMF version of 
that looks like this:


http://dev.plone.org/plone/browser/plone.z3cform/trunk/plone/z3cform/add.py

z3c.form is generally nicer to work with than formlib.


Maybe we should discuss this in a different thread. Here a short reply: 
My code for the AddForm would look quite different, especially for CMF 
trunk, 


I'm curious how it would look different. Now is the time to get the 
correct base class behavior in plone.z3cform, before we release a new 
version of it.


but in general that's the way to go. Since z3c.form became the 
standard in the Zope 3 world I'd like to see Zope 2 and CMF moving in 
the same direction. Unfortunately using plone.z3cform is no option for 
CMF because it has a different license and repository. *If* Plone wants 
to donate that code to the Zope Foundation or someone writes something 
similar (maybe five.z3cform), I'd be happy to help with CMF integration.


Bah, I hate these discussions. I'm sure Daniel Nouri would be happy to 
relicense. Re-invention for the sake of a license is just too dumb.


I'd prefer to keep the name to avoid breaking existing packages, though.

Another option is to factor out a few things to a five.z3cform and have 
plone.z3cform import from it as appropriate.


In any case, I'd like to know why you went down the portal_actions route 
for rendering the add links. I'm not quite sure I like the idea of 
having this be persistent configuration, separate to the FTI, as the two 
would need to be kept in sync, and in sync with the view name registered 
in ZCML.


CMF makes a distinction between portal types and content types. Portal 
types are persistent wrappers around the non-persistent content types. 
You can define many different portal types based on one content type.


Right.

In CMF you add *portal type* instances, so the 'add' links should be 
persistent as well. The non-persistent add form has to take the portal 
type name as argument to create the correct portal type.


I'm not sure what the right solution is, but I guess extending the type 
info classes will be the best approach.


Also, why not try to use the Zope 3 menu concept? There's even a special 
add menu directive.


Moving away from persistent actions is not on my todo list. And as I 
tried to explain above, the current portal type concept depends on 
persistent actions.


Right, I see that. But having things in two places is obviously not very 
desirable either.


I'd quite like to find a good approach here that can be used by both 
Plone and plain CMF, if possible.


I hope you find one ;)


How about we use a naming convention that's linked to the factory that's 
persisted in the FTI, i.e. we look for a view called 
add-factory_name and link to that if it's available.


The idea is that the factory name is unique and specific to the content 
type. Different portal types that use the same factory would almost by 
necessity have the same add view.


We could make this overrideable as well, with another FTI property.

The assumption here is that the add menu is rendered with some custom 
code, i.e. it doesn't use the actions machinery or the Zope 3 browser 
menu concept.


Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Tres Seaver
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Martin Aspeli wrote:
 Hi folks,
 
 I see that Yuppie has been experimenting with add forms. From what I can 
 tell, he's using a custom formlib base class and registering views as 
 e.g. addFile.html. It also look as if he's registering that view as an 
 action in portal_actions, in the 'folder' category.
 
 Plone currently supports add forms for the IAdding (+) view in a 
 somewhat ugly way (it looks to see if there's a view for IAdding with 
 the same name as the 'factory' set in the FTI of an addable type, and if 
 so, provides a link to it). IAdding can be a bit painful, so we're 
 interested in supporting an approach based on simple views.
 
 It's also worth noting that z3c.form (via plone.z3cform, which should be 
 plain CMF compatible, though you may want a different default template) 
 has support for such views in quite a generic way. The CMF version of 
 that looks like this:
 
 http://dev.plone.org/plone/browser/plone.z3cform/trunk/plone/z3cform/add.py
 
 z3c.form is generally nicer to work with than formlib.
 
 In any case, I'd like to know why you went down the portal_actions route 
 for rendering the add links. I'm not quite sure I like the idea of 
 having this be persistent configuration, separate to the FTI, as the two 
 would need to be kept in sync, and in sync with the view name registered 
 in ZCML.

Putting the policy in the typeinfo objects seems like a much saner place
to keep this stuff than embedding it in a component registry.

 Also, why not try to use the Zope 3 menu concept? There's even a special 
 add menu directive.

The Z3 menu stuff seems to me bound up with the needs of the
never-gonna-use-it Z3MI:  it is overcomplicated for little purpose, and
puts too much policy into emergent behavior (ordering of component
lookups, for instance).

 I'd quite like to find a good approach here that can be used by both 
 Plone and plain CMF, if possible.


Tres.
- --
===
Tres Seaver  +1 540-429-0999  [EMAIL PROTECTED]
Palladion Software   Excellence by Designhttp://palladion.com
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFIegPw+gerLs4ltQ4RAhheAKCQdKEg+O/y4OM42zYJQ5vHNJSRngCfagdO
rUEaTSE/XFT6sw7sUTUgrQ8=
=L3iv
-END PGP SIGNATURE-

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


Re: [Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Charlie Clark


Am 13.07.2008 um 14:08 schrieb Martin Aspeli:

Thanks for restarting the discussion and thanks to Yuppie for his  
implementation. We've been using it with the changes I outlined the  
other week to good effect for the last couple of months.


Bah, I hate these discussions. I'm sure Daniel Nouri would be happy  
to relicense. Re-invention for the sake of a license is just too dumb.


I think we all hate such discussions but that's the way it is when  
derivative code gets given a different licence.


I'd prefer to keep the name to avoid breaking existing packages,  
though.


Another option is to factor out a few things to a five.z3cform and  
have plone.z3cform import from it as appropriate.


This is probably necessary anyway. I'm not sure whether it's right to  
try and go straight to z3c.form. My understanding is that there isn't  
a great deal of difference between the two libraries so hopefully an  
implementation could live with both. I don't think that everyone has  
moved onto z3c.form - certainly that wasn't my impression at  
Europython. It would be nice to have a formlib based CMF 2.2 and I  
think I now understand most of this well enough to contribut. We could  
possibly  onto z3c.form in 2.3 which might have replaced zope.formlib  
in Zope by then.


In any case, I'd like to know why you went down the portal_actions  
route for rendering the add links. I'm not quite sure I like the  
idea of having this be persistent configuration, separate to the  
FTI, as the two would need to be kept in sync, and in sync with  
the view name registered in ZCML.
CMF makes a distinction between portal types and content types.  
Portal types are persistent wrappers around the non-persistent  
content types. You can define many different portal types based on  
one content type.


Right.

In CMF you add *portal type* instances, so the 'add' links should  
be persistent as well. The non-persistent add form has to take the  
portal type name as argument to create the correct portal type.
I'm not sure what the right solution is, but I guess extending the  
type info classes will be the best approach.


Also, why not try to use the Zope 3 menu concept? There's even a  
special add menu directive.
Moving away from persistent actions is not on my todo list. And as  
I tried to explain above, the current portal type concept depends  
on persistent actions.


Right, I see that. But having things in two places is obviously not  
very desirable either.


I'd quite like to find a good approach here that can be used by  
both Plone and plain CMF, if possible.

I hope you find one ;)


How about we use a naming convention that's linked to the factory  
that's persisted in the FTI, i.e. we look for a view called add- 
factory_name and link to that if it's available.


You might as well stick with actions if you're going to do that. I've  
been experimenting with the following


portal_type = self.request.form.get('portal_type')
at = getToolByName(self.context, 'portal_actions')
actions = at.listFilteredActionsFor(self.context)
addable = actions.get('add', [])
for a in addable:
if a['id'] == portal_type:
	return request.response(%s/%s (%self.context.absolute_url(),  
a['url']))


It's workable but so easy to break as it relies on add actions  
having the same name as the portal_type. It makes much more sense to  
me to have this on the type info: if I ask the type tool for the  
factory, surely I can also ask it for the view?


The idea is that the factory name is unique and specific to the  
content type. Different portal types that use the same factory would  
almost by necessity have the same add view.


We could make this overrideable as well, with another FTI property.

The assumption here is that the add menu is rendered with some  
custom code, i.e. it doesn't use the actions machinery or the Zope 3  
browser menu concept.



Yes, I think that has to be the case.

Charlie
--
Charlie Clark
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-938-5360
GSM: +49-178-782-6226



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread yuppie

Hi Martin!


Martin Aspeli wrote:

Martin Aspeli wrote:
It's also worth noting that z3c.form (via plone.z3cform, which should 
be plain CMF compatible, though you may want a different default 
template) has support for such views in quite a generic way. The 
CMF version of that looks like this:


http://dev.plone.org/plone/browser/plone.z3cform/trunk/plone/z3cform/add.py 



z3c.form is generally nicer to work with than formlib.


Maybe we should discuss this in a different thread. Here a short 
reply: My code for the AddForm would look quite different, especially 
for CMF trunk, 


I'm curious how it would look different. Now is the time to get the 
correct base class behavior in plone.z3cform, before we release a new 
version of it.


Ok. I added some comments to the 'add' method of plone.z3cform:


def add(self, object):

container = aq_inner(self.context)

content = object

name = self.contentName

chooser = INameChooser(container)

# Ensure that construction is allowed

portal_types = getToolByName(container, 'portal_types')
fti = portal_types.getTypeInfo(content)

if fti is not None:
# Check add permission
if not fti.isConstructionAllowed(container):
raise Unauthorized(uYou are not allowed to create a %d here % 
fti.getId())


Inside an add form this should always be true. If it isn't true, we'll 
get an error anyway. So this check is redundant and can be removed.



# Check allowable content types
if  getattr(aq_base(container), 'allowedContentTypes', None) is not 
None and \
not fti.getId() in container.allowedContentTypes():
raise Unauthorized(uYou are not allowed to create a %d here % 
fti.getId())


allowedContentTypes is quite expensive. I use this code instead:

  #check container constraints
  container_ti = portal_types.getTypeInfo(container)
  portal_type = content.getPortalTypeName()
  if container_ti is not None and \
  not container_ti.allowType(portal_type):
  raise ValueError('Disallowed subobject type: %s' % portal_type)


# check preconditions
checkObject(container, name, content)


I doubt constraints based on __setitem__ and __parent__ work in Zope 2.


if IContainerNamesContainer.providedBy(container):
# The container picks it's own names.
# We need to ask it to pick one.
name = chooser.chooseName(self.contentName or '', content)
else:
request = self.request
name = request.get('add_input_name', name)

if name is None:
name = chooser.chooseName(self.contentName or '', content)
elif name == '':
name = chooser.chooseName('', content)
else:
# Invoke the name chooser even when we have a
# name. It'll do useful things with it like converting
# the incoming unicode to an ASCII string.
name = chooser.chooseName(name, container)

if not name:

raise ValueError(Cannot add content: name chooser did not provide a 
name)


All that name handling is copied from an old version of Five's 
BasicAdding, which in turn is copied from old Zope 3 code. I think we 
should use our own code here to make sure we understand the code and it 
reflects our policy.


Creating the content I set a provisional id. In the 'add' method I just 
use this line:


  name = chooser.chooseName(content.getId(), content)


content.id = name
container._setObject(name, content)
content = container._getOb(name)

if fti is not None:

fti._finishConstruction(content)


CMF trunk uses events instead of _finishConstruction.


self.contentName = name


but in general that's the way to go. Since z3c.form became the 
standard in the Zope 3 world I'd like to see Zope 2 and CMF moving in 
the same direction. Unfortunately using plone.z3cform is no option for 
CMF because it has a different license and repository. *If* Plone 
wants to donate that code to the Zope Foundation or someone writes 
something similar (maybe five.z3cform), I'd be happy to help with CMF 
integration.


Bah, I hate these discussions. I'm sure Daniel Nouri would be happy to 
relicense. Re-invention for the sake of a license is just too dumb.


I'd prefer to keep the name to avoid breaking existing packages, though.

Another option is to factor out a few things to a five.z3cform and have 
plone.z3cform import from it as appropriate.


+1

plone.z3cform seems to contain Plone specific stuff. Factoring out the 
generic stuff to a five.z3cform package sounds good to me.


But I don't know if everybody agrees that CMF 2.2 should depend on z3c.form.

How about we use a naming convention that's linked to the factory that's 
persisted in the FTI, i.e. we look for a view 

[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Martin Aspeli

Charlie Clark wrote:

This is probably necessary anyway. I'm not sure whether it's right to  
try and go straight to z3c.form. My understanding is that there isn't  
a great deal of difference between the two libraries so hopefully an  
implementation could live with both. I don't think that everyone has  
moved onto z3c.form - certainly that wasn't my impression at  
Europython. It would be nice to have a formlib based CMF 2.2 and I  
think I now understand most of this well enough to contribut. We could  
possibly  onto z3c.form in 2.3 which might have replaced zope.formlib  
in Zope by then.


I doubt that formlib will be replaced by z3c.form. Rather, it just seems 
that everyone prefers to work with the latter and so the former is 
becoming less relevant.


They are definitely different, and don't share any code as far as I 
know, but if you know one, moving to the other is pretty trivial. 
z3c.form also has good (if a bit too abundant) documentation.


Thus, if CMF hasn't yet picked a form library in a release, then you 
could try to learn from Plone's mistakes and not jump on a sinking ship. :)


How about we use a naming convention that's linked to the factory  
that's persisted in the FTI, i.e. we look for a view called add- 
factory_name and link to that if it's available.


You might as well stick with actions if you're going to do that. I've  
been experimenting with the following


portal_type = self.request.form.get('portal_type')
at = getToolByName(self.context, 'portal_actions')
actions = at.listFilteredActionsFor(self.context)
addable = actions.get('add', [])
for a in addable:
 if a['id'] == portal_type:
	return request.response(%s/%s (%self.context.absolute_url(),  
a['url']))


It's workable but so easy to break as it relies on add actions  
having the same name as the portal_type. It makes much more sense to  
me to have this on the type info: if I ask the type tool for the  
factory, surely I can also ask it for the view?


You mean we have an action on the FTI object with category 'add' and 
name == FTI name/portal_type? That still means having to get that link 
right, though (a typo in the FTI name or a rename of the FTI makes it 
break), and I question whether you ever need all the other info that 
actions provide. We already have ways to control add permissions and 
other filters for what's addable where.


Martin


--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Martin Aspeli

Hi Tres,


Putting the policy in the typeinfo objects seems like a much saner place
to keep this stuff than embedding it in a component registry.


+1, at least if we're talking about persistent configuration (which I 
guess we are).


Do you have a preference for what shape this should take?

 - A simple property 'addview' that gives a view name?

 - A simple property 'addview' that gives a view name in a TALES 
expression?


 - Something using FTI actions?

 - Something else?

Also, why not try to use the Zope 3 menu concept? There's even a special 
add menu directive.


The Z3 menu stuff seems to me bound up with the needs of the
never-gonna-use-it Z3MI:  it is overcomplicated for little purpose, and
puts too much policy into emergent behavior (ordering of component
lookups, for instance).


Plone uses it to make the content menu (the green bar in the 
editable border) somewhat pluggable and customiseable-by-context. In 
hindsight, we could probably just as easily have invented our own 
interfaces and used that instead of the ones in zope.app.publisher, 
though I don't think they've done too much harm either.


The ordering thing is irritating though.

For add menus, however, there *may* be a purpose to using it since Zope 
3 has a specific ZCML directive to declare your add action. At least 
we should consider it.


Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Martin Aspeli

Hi Yuppie,


Ok. I added some comments to the 'add' method of plone.z3cform:


Thanks for that!


def add(self, object):

container = aq_inner(self.context)

content = object

name = self.contentName

chooser = INameChooser(container)

# Ensure that construction is allowed

portal_types = getToolByName(container, 'portal_types')
fti = portal_types.getTypeInfo(content)

if fti is not None:
# Check add permission
if not fti.isConstructionAllowed(container):
raise Unauthorized(uYou are not allowed to create a %d here % 
fti.getId())


Inside an add form this should always be true. If it isn't true, we'll 
get an error anyway. So this check is redundant and can be removed.


Cool.


# Check allowable content types
if  getattr(aq_base(container), 'allowedContentTypes', None) is not 
None and \
not fti.getId() in container.allowedContentTypes():
raise Unauthorized(uYou are not allowed to create a %d here % 
fti.getId())


allowedContentTypes is quite expensive. I use this code instead:

   #check container constraints
   container_ti = portal_types.getTypeInfo(container)
   portal_type = content.getPortalTypeName()
   if container_ti is not None and \
   not container_ti.allowType(portal_type):
   raise ValueError('Disallowed subobject type: %s' % portal_type)


Nice!


# check preconditions
checkObject(container, name, content)


I doubt constraints based on __setitem__ and __parent__ work in Zope 2.


Well, they do in the sense that if you have them and we have this code, 
we'll get an exception. They don't work generally, tough, so this may be 
YAGNI. It was copied from Five's Adding implementation, so I figured it 
should be kept if someone's relying on it.



if IContainerNamesContainer.providedBy(container):
# The container picks it's own names.
# We need to ask it to pick one.
name = chooser.chooseName(self.contentName or '', content)
else:
request = self.request
name = request.get('add_input_name', name)

if name is None:
name = chooser.chooseName(self.contentName or '', content)
elif name == '':
name = chooser.chooseName('', content)
else:
# Invoke the name chooser even when we have a
# name. It'll do useful things with it like converting
# the incoming unicode to an ASCII string.
name = chooser.chooseName(name, container)

if not name:

raise ValueError(Cannot add content: name chooser did not provide a 
name)


All that name handling is copied from an old version of Five's 
BasicAdding, which in turn is copied from old Zope 3 code. I think we 
should use our own code here to make sure we understand the code and it 
reflects our policy.


Yeah, that code's pretty nuts and doesn't make a lot of sense. I tried 
to refactor it when I copied it over, actually, and then found that I 
didn't really understand it so I left it alone.


Creating the content I set a provisional id. In the 'add' method I just 
use this line:


   name = chooser.chooseName(content.getId(), content)


+1


content.id = name
container._setObject(name, content)
content = container._getOb(name)

if fti is not None:

fti._finishConstruction(content)


CMF trunk uses events instead of _finishConstruction.


Ah, nice. Do you think it'd be feasible to backport this, i.e. copy the 
event handler somewhere in Plone so long as Plone's still using an older 
version of CMF? Or does the new event handler rely on other changes to 
CMF as well?


Another option is to factor out a few things to a five.z3cform and have 
plone.z3cform import from it as appropriate.


+1

plone.z3cform seems to contain Plone specific stuff. Factoring out the 
generic stuff to a five.z3cform package sounds good to me.


I'm CC'ing Daniel Nouri if he has an opinion. I think it should be 
unproblematic to test this stuff out in plone.z3cform and then have it 
depend on a new five.z3cform and just do convenience imports where required.



But I don't know if everybody agrees that CMF 2.2 should depend on z3c.form.


CMFCore shouldn't need to. CMFDefault may want to though.

How about we use a naming convention that's linked to the factory that's 
persisted in the FTI, i.e. we look for a view called 
add-factory_name and link to that if it's available.


The idea is that the factory name is unique and specific to the content 
type.


I sometimes use different factories for one content type, but a 1:1 
relationship doesn't seem to be necessary for your proposal.


Different portal types that use the same factory would almost by 
necessity have the same add view.


This is the 

Re: [Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Charlie Clark


Am 13.07.2008 um 20:21 schrieb Martin Aspeli:

I doubt that formlib will be replaced by z3c.form. Rather, it just  
seems that everyone prefers to work with the latter and so the  
former is becoming less relevant.


I wonder who everyone is? When I asked Maartijn Faassen as  
Europython he didn't seem to be in a hurry to migrate Grok to using  
z3c.form and his work on Formulator was possibly the start of a Zope  
forms library of which formlib and z3c.form are the nth and n+1th  
generations.


They are definitely different, and don't share any code as far as I  
know, but if you know one, moving to the other is pretty trivial.  
z3c.form also has good (if a bit too abundant) documentation.


I've only briefly looked at z3c.form but it seems to make abundant  
reference to how zope.formlib works.


Thus, if CMF hasn't yet picked a form library in a release, then you  
could try to learn from Plone's mistakes and not jump on a sinking  
ship. :)


We're already using zope.formlib in the experimental browser views  
edit forms. The reference to a sinking ship is totally off-target. My  
own view is that sometimes it is better to wait for version 2 of a  
product or library to be released before adoption. Surely Plone has  
suffered from adopting some stuff too early?


How about we use a naming convention that's linked to the factory   
that's persisted in the FTI, i.e. we look for a view called add-  
factory_name and link to that if it's available.
You might as well stick with actions if you're going to do that.  
I've  been experimenting with the following

portal_type = self.request.form.get('portal_type')
at = getToolByName(self.context, 'portal_actions')
actions = at.listFilteredActionsFor(self.context)
addable = actions.get('add', [])
for a in addable:
if a['id'] == portal_type:
	return request.response(%s/%s (%self.context.absolute_url(),   
a['url']))
It's workable but so easy to break as it relies on add actions   
having the same name as the portal_type. It makes much more sense  
to  me to have this on the type info: if I ask the type tool for  
the  factory, surely I can also ask it for the view?


You mean we have an action on the FTI object with category 'add' and  
name == FTI name/portal_type? That still means having to get that  
link right, though (a typo in the FTI name or a rename of the FTI  
makes it break), and I question whether you ever need all the other  
info that actions provide. We already have ways to control add  
permissions and other filters for what's addable where.



Yes, which is why I don't favour this approach: it can work but is  
likely to cause problems.


What we all want is to be able to get the add view for a particular  
portal_type but we can't do this through QueryMultiAdapter because the  
view has to be registered on a container. Actions are unsuitable but  
provided Yuppie with a bootstrap to test the whole procedure and  
highlight the deficiencies. I'm afraid I don't understand the  
internals too well but isn't something like cmf:registerAddView ...  
or what we're after until the Zope 3 world comes up with the right  
way to do this?


Charlie
--
Charlie Clark
Helmholtzstr. 20
Düsseldorf
D- 40215
Tel: +49-211-938-5360
GSM: +49-178-782-6226



___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Martin Aspeli

Charlie Clark wrote:

Am 13.07.2008 um 20:21 schrieb Martin Aspeli:

I doubt that formlib will be replaced by z3c.form. Rather, it just  
seems that everyone prefers to work with the latter and so the  
former is becoming less relevant.


I wonder who everyone is? When I asked Maartijn Faassen as  
Europython he didn't seem to be in a hurry to migrate Grok to using  
z3c.form and his work on Formulator was possibly the start of a Zope  
forms library of which formlib and z3c.form are the nth and n+1th  
generations.


Well, let me put it another way then: A lot of people have expressed 
dissatisfaction with formlib and seem to like z3c.form better.


They are definitely different, and don't share any code as far as I  
know, but if you know one, moving to the other is pretty trivial.  
z3c.form also has good (if a bit too abundant) documentation.


I've only briefly looked at z3c.form but it seems to make abundant  
reference to how zope.formlib works.


Right. z3c.form is an attempt to rectify some of the mistakes from 
zope.formlib and build something better.


Thus, if CMF hasn't yet picked a form library in a release, then you  
could try to learn from Plone's mistakes and not jump on a sinking  
ship. :)


We're already using zope.formlib in the experimental browser views  
edit forms. The reference to a sinking ship is totally off-target. My  
own view is that sometimes it is better to wait for version 2 of a  
product or library to be released before adoption. Surely Plone has  
suffered from adopting some stuff too early?


*shrug*

Do what you please. I'm not particularly wedded to one or the other. But 
having used both, I'm pretty sure that z3c.form is a better library. In 
many ways, z3c.form *is* version 2 of formlib.


Yes, which is why I don't favour this approach: it can work but is  
likely to cause problems.


I don't have an approach, I'm trying to find one that works. I'm not 
sure what problems you're referring to, though.


What we all want is to be able to get the add view for a particular  
portal_type but we can't do this through QueryMultiAdapter because the  
view has to be registered on a container.'


Mmmm... I'm not sure I follow here. The issue is how to render the 
correct link to the add view for each addable type. You loop through the 
addable types and then render a list of links. If by queryMultiAdapter 
you mean the browser view lookup, then that's something the publisher 
does when someone clicks the link, not something we'd do to find out 
what those links are.


Actions are unsuitable but  
provided Yuppie with a bootstrap to test the whole procedure and  
highlight the deficiencies.


Obviously.

I'm afraid I don't understand the  
internals too well but isn't something like cmf:registerAddView ...  
or what we're after until the Zope 3 world comes up with the right  
way to do this?


Zope 3 has a way, it's called browser:addMenuItem / (or something like 
that). However, Tres and Yuppie have pointed out reasons why doing this 
with global component registrations is not ideal.


Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Daniel Nouri
Martin Aspeli writes:
 Yuppie writes:
 but in general that's the way to go. Since z3c.form became the
 standard in the Zope 3 world I'd like to see Zope 2 and CMF moving
 in the same direction. Unfortunately using plone.z3cform is no
 option for CMF because it has a different license and
 repository. *If* Plone wants to donate that code to the Zope
 Foundation or someone writes something similar (maybe five.z3cform),
 I'd be happy to help with CMF integration.

 Bah, I hate these discussions. I'm sure Daniel Nouri would be happy to
 relicense. Re-invention for the sake of a license is just too dumb.

 I'd prefer to keep the name to avoid breaking existing packages, though.

 Another option is to factor out a few things to a five.z3cform and
 have plone.z3cform import from it as appropriate.

I just relicensed and moved plone.z3cform to the Zope repository:

  http://svn.zope.org/plone.z3cform/trunk/

Despite the plone namespace, it works fine in CMF and pure Zope 2.
*Some* of the functionality (modules) is Plone or CMF specific.  The
default configure.zcml aims to be usable without Plone or CMF.

There's a buildout.cfg in there that pulls Plone.  I'd like to replace
it with a Zope2-only one (and maybe move the existing buildout to
another location).  The tests work without Plone.


Daniel

___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-13 Thread Philipp von Weitershausen

Daniel Nouri wrote:

Martin Aspeli writes:

Yuppie writes:

but in general that's the way to go. Since z3c.form became the
standard in the Zope 3 world I'd like to see Zope 2 and CMF moving
in the same direction. Unfortunately using plone.z3cform is no
option for CMF because it has a different license and
repository. *If* Plone wants to donate that code to the Zope
Foundation or someone writes something similar (maybe five.z3cform),
I'd be happy to help with CMF integration.

Bah, I hate these discussions. I'm sure Daniel Nouri would be happy to
relicense. Re-invention for the sake of a license is just too dumb.

I'd prefer to keep the name to avoid breaking existing packages, though.

Another option is to factor out a few things to a five.z3cform and
have plone.z3cform import from it as appropriate.


I just relicensed and moved plone.z3cform to the Zope repository:

  http://svn.zope.org/plone.z3cform/trunk/


Yay!


Despite the plone namespace, it works fine in CMF and pure Zope 2.


A namespace is just a name :).


*Some* of the functionality (modules) is Plone or CMF specific.  The
default configure.zcml aims to be usable without Plone or CMF.

There's a buildout.cfg in there that pulls Plone.  I'd like to replace
it with a Zope2-only one (and maybe move the existing buildout to
another location).


+100


The tests work without Plone.


Awesome.


By the way, I've collected a few conventions about maintaining software 
in svn.zope.org:


http://svn.zope.org/*checkout*/Sandbox/philikon/foundation/maintaining-software.txt
http://svn.zope.org/*checkout*/Sandbox/philikon/foundation/releasing-software.txt

It would be nice if everything in svn.zope.org would adhere to these 
conventions. I'm just mentioning this since there may be some 
differences to Plone's conventions.


___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests


[Zope-CMF] Re: Add forms and menus

2008-07-12 Thread yuppie

Hi Martin!


Martin Aspeli wrote:
I see that Yuppie has been experimenting with add forms. From what I can 
tell, he's using a custom formlib base class and registering views as 
e.g. addFile.html. It also look as if he's registering that view as an 
action in portal_actions, in the 'folder' category.


That's correct. But I have to mention that not all parts of these 
changes have reached the same stage of maturation. Using 'folder' 
category Actions is a temporary hack to generate menu items for the new 
add forms. I'm glad you want to help to find a better solution.


Plone currently supports add forms for the IAdding (+) view in a 
somewhat ugly way (it looks to see if there's a view for IAdding with 
the same name as the 'factory' set in the FTI of an addable type, and if 
so, provides a link to it). IAdding can be a bit painful, so we're 
interested in supporting an approach based on simple views.


Good.

It's also worth noting that z3c.form (via plone.z3cform, which should be 
plain CMF compatible, though you may want a different default template) 
has support for such views in quite a generic way. The CMF version of 
that looks like this:


http://dev.plone.org/plone/browser/plone.z3cform/trunk/plone/z3cform/add.py

z3c.form is generally nicer to work with than formlib.


Maybe we should discuss this in a different thread. Here a short reply: 
My code for the AddForm would look quite different, especially for CMF 
trunk, but in general that's the way to go. Since z3c.form became the 
standard in the Zope 3 world I'd like to see Zope 2 and CMF moving in 
the same direction. Unfortunately using plone.z3cform is no option for 
CMF because it has a different license and repository. *If* Plone wants 
to donate that code to the Zope Foundation or someone writes something 
similar (maybe five.z3cform), I'd be happy to help with CMF integration.


In any case, I'd like to know why you went down the portal_actions route 
for rendering the add links. I'm not quite sure I like the idea of 
having this be persistent configuration, separate to the FTI, as the two 
would need to be kept in sync, and in sync with the view name registered 
in ZCML.


CMF makes a distinction between portal types and content types. Portal 
types are persistent wrappers around the non-persistent content types. 
You can define many different portal types based on one content type.


In CMF you add *portal type* instances, so the 'add' links should be 
persistent as well. The non-persistent add form has to take the portal 
type name as argument to create the correct portal type.


I'm not sure what the right solution is, but I guess extending the type 
info classes will be the best approach.


Also, why not try to use the Zope 3 menu concept? There's even a special 
add menu directive.


Moving away from persistent actions is not on my todo list. And as I 
tried to explain above, the current portal type concept depends on 
persistent actions.


I'd quite like to find a good approach here that can be used by both 
Plone and plain CMF, if possible.


I hope you find one ;)


Cheers,

Yuppie


___
Zope-CMF maillist  -  Zope-CMF@lists.zope.org
http://mail.zope.org/mailman/listinfo/zope-cmf

See http://collector.zope.org/CMF for bug reports and feature requests