[Zope] Product development

Brian Lloyd brian@digicool.com
Fri, 20 Jul 2001 13:38:33 -0400


 Zope product development tip-o-the-day :)
 

> I have some problems creating my first product. I've read the
> Developers Guide and the boring product, but I could not solve 2
> problems:
> 
> 1.) I can select my product from the add list, but
> whenever I try to add it to the folder (after submitting the add form)
> I get an error message: KeyError: manage_page_header
> When I access manage_main via the 'edit' tab of an already created
> product, this error does not appear.

This one I can help with :) The problem is in the "constructor" 
(or factory) method for the Article object:

> def addMethod(self, id, REQUEST=None):
>      """
>      Create a new article
>      """
>      a = Article(id) 
>      self._setObject(id, a)
>      if REQUEST is not None:
>           return a.edit(REQUEST)


What is happening here is that 'a' is a new instance of 
Article, which you add to 'self' (the container). The reason 
why you get an error when trying to render the manage_main 
dtml (a.edit) is that 'a' is not wrapped in any Acquisition 
context. It works for you later via the 'edit' tab because 
then you are accessing it in such a way that it is wrapped. 
It needs to be wrapped because the ZMI needs to be able to 
get certain things via acquisition.

The solution here is to arrange to get a wrapped version of 
the new Article instance before trying to render the dtml:

def addMethod(self, id, REQUEST=None):
     """
     Create a new article
     """
     a = Article(id) 
     self._setObject(id, a)
     # get a wrapped version of the new instance...
     wrapped = self._getOb(id)
     if REQUEST is not None:
          return wrapped.edit(REQUEST)

Note that a way many people avoid having to remember this is to 
do a redirect at the end of the factory method rather than rendering
the result dtml directly. A common paradigm in the Zope source is:

def addMethod(self, id, REQUEST=None):
     """
     Create a new article
     """
     # In your case, you want to redirect to the manage_main of the
     # newly created object. Since you don't need to use anything 
     # from the new instance directly when you do a redirect, you 
     # wouldn't have to worry about wrapping it.
     a = Article(id) 
     self._setObject(id, a)
    if REQUEST is not None:
        redirect_to = '%s/%s/manage_main' % (REQUEST['URL1'], id)
        REQUEST['RESPONSE'].redirect(redirect_to)

> 
> 2.) I want to add some properties to my product. So I defined the
> _properties variable, but my property 'color' does not appear on the
> property manage interface.

> 
>      _properties=({'id':'color', 'type': 'selection', 'mode': 
> 'w', 'select_variable': 'getColors'},
>                   )

I _suspect_ (but I can't verify, since I can't get to the docs at
the moment and I haven't used the selection / select_variable stuff 
very much myself) that 'getColors' also has to be a property. The 
Zope book (online) should be able to clarify that.

Hope this helps!


Brian Lloyd        brian@digicool.com
Software Engineer  540.371.6909              
Digital Creations  http://www.digicool.com