[Zope] Python based ZClass Questions

Andrew Lahser andrew@apl-software.com
Fri, 4 Feb 2000 23:26:55 -0500


From: James W. Howe <jwh@allencreek.com>


> First, if I create a Python base class, should I use it to control the the
> collection of base classes used by my ZClass?  For example, suppose that I
> originally create a ZClass which has a base of MyPythonBase.  Suppose that
> MyPythonBase does not inherit from something like ObjectManager.  Later I
> decide that my ZClass needs to have ObjectManager behavior.  Can I modify
> my base class to now inherit from ObjectManager?
>
I have tried to do just this with ObjectManager and CatalogAware. I had
horrible luck trying to get the ObjectManager and CatalogAware functionality
to work correctly. Moreover, I had to have CatalogAware first and
ObjectManager second and MyPythonBase third to get the functionality that
I wanted in ZPhotoAlbum (part of Zope Photo Product). The killer thing -- I
still don't understand why I had these problems. The only way I could get
the
functionality I wanted was to sub class these in the ZClass, even though I
would have preferred to do this in python.

Of course, the other alternative is to do 100% python, which means you can
get the exact sub-classing that you are looking for every time. No fuss, no
muss.
But, of course, then your product won't be extensible my your
content-manager.
And you have to restart Zope every time you make the smallest change.

I had fabulous luck reseting the base class of my ZClass after the fact.
For info on that, visit my UNCATALOGED tip.
http://www.zope.org/Members/Drew/tips/changing_zclass_base_class
I don't know the caveats of using this, but for adding in CatalogAware and
ObjectManger, or doing reordering, this seems to work better than trying
to add classes in your base class. I have done this a half dozen times with
out any side effects.

> Second, if I define my base class inheritance from the ZClass definition
> interface, when I define new ZClasses which inherit from my Python base
> class, should I put my base class first in the list of base classes or
> last?  If I understand how inheritance works, attributes are searched
depth
> first, left to right.  I believe this means that if I wanted to override
> some behavior of one of the other inherited classes, I would have to have
> my class first.  What are the pros and cons of having my base class first
> or last?
>
Still, I would put CatalogAware first, ObjectManager second, your class
third.
Alternately, you can put your base class first and define the elements of
CatalogAware or ObjectManager that you like. For a good example of this,
take a look at ZDiscussions. http://www.zope.org/Members/MikeP/ZDiscussions
ZDiscussions creates its own CatalogAware methods.

> Finally, I've noticed that when a ZClass is defined, a predefined set of
> "views" are created for the object.  For example, the "Contents" view
might
> have "manage_main" and something else defined as available view
> methods.  If methods are added to the ZClass, they show up in the list.
If
> I wanted to define some new methods at the Python level, what do I need to
> do to have them show up in the view list?  For example, suppose that I
> create a subclass of Folder and I want to have an alternative way to view
> the my folders contents.  I can think of two ways to make this
> work.  First, make sure that my base class is first in the inheritance
list
> and then override the definition of something like "manage_main",
> substituting my DTML code for the standard DTML code.  Alternatively, I
> could define a new method in my ZClass which has the DTML code I
> desire.  What I'd like to know is how I could define a new method in my
> Python code and have it selectable as an available view.
>
This is easier than you describe. Each python class can define an attribute
called manage_options. This is a tuple of dictionary items that define the
methods that appear as TABS in the management screens. Here is an
example.

class Photo
    ...blah...
    manage_options=({'label':'Edit', 'action':'manage_main'},
                    {'label':'Upload', 'action':'manage_uploadForm'},
                    {'label':'Displays', 'action':'manage_displays'},
                    {'label':'Properties',
'action':'manage_propertiesForm'},
                    {'label':'View', 'action':'view_image_or_file'},
                    {'label':'Security', 'action':'manage_access'},
                    )
   ...blah, blah...

You may also want to look at DTMLTemplate you have not already
done so. For example

class Photo
    ...blah....
    manage_displays=HTMLFile('displays',globals())
    ....blah....

Then in the same directory there is a file called displays.dtml that sort of
looks like this.

...snip...
<dtml-in displayMap mapping>
<tr>
  <td align="left" valign="top">
  <input type="checkbox" name="ids:list" value="<dtml-var id html_quote>"
ID="cb-&dtml-id;">
  </td>
...snip...
  <dtml-if expr="meta_type != 'ZPhotoAlbum'">
  <td align="right" valign="top">
    <dtml-var actual_width> x <dtml-var actual_height>
  </td>
  </dtml-if>
</dtml-in>
...snip...

The important part here is that this is just DTML, but it is in a file
in the file system. I apologize if you have already seen this nifty feature.

Anyway, all of these methods, including the DTML method defined by the
DTMLTemplate above, will show up in the view list. Note that neither
CatalogAware or ObjectManager define a manage_main, so the
manage_main is your base class will be available.

HTH

"Drew"