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"