[ZDP] FAQ 0.2 - Product Development

Martijn Faassen M.Faassen@vet.uu.nl
Tue, 09 Mar 1999 19:38:48 +0100


Zope FAQ 0.2 - Product Development

* How does my Folder Product load default documents?

    Create a list of tuples containing filenames (without '.dtml') and
    title pairs::

        self.defaultDocs = [
            ('index', 'NotMail'),
            ('address', 'Address Book'),
            ('attach', 'Attach a File'),
            ('composer', 'Compose a Message'),
            ('contact', 'Contact Developers'),
            ('search', 'Search Your Mailboxes'),
            ('results', 'Your Search Results'),
            ('folder', 'Mailbox'),
            ('message', 'Message'),
            ('help', 'Help'),
            ('lookup', 'Lookup Users'),
            ('standard_footer', 'Standard HTML Footer'),
            ('standard_header', 'Standard HTML Header'),
            ('noto', 'Message must have at least one recipient.'),
            ('reminders', 'Your Reminders'),
            ('save', 'Save Message'),
            ('logout', 'You have been logged out'),
            ('GPL', 'The GNU General Public License'),
            ('sentmail', 'Mail was sent')]

        # Then iterate over them and create each one

        for id,title in self.defaultDocs:
            try:
                self.defaultDocFile(id, title, id)
            except:
                pass

        # defaultDocFile is a handy little function:

        def defaultDocFile(self, id, title, file):
            f=open('%s/Products/NotMail/%s.dtml'
                   % (SOFTWARE_HOME, file))
            file=f.read()
            f.close()
            self.manage_addDocument(id, title, file)

    When you are debugging your DTML, it's a pain to keep deleting and
    creating new instances of your object in order to load the new
    dtml files off of the disk. This function comes in handy::

        def refresh_docs(self, REQUEST):
            """ refresh documents from disk (for debug purposes) """
            
            for id,title in self.defaultDocs:
                try:
                    self._delObject(id)
                except:
                    pass
                try:
                    self.defaultDocFile(id, title, id)
                except:
                    pass
            return self.manage_main(self, REQUEST)

    Then, assuming your object has an attribute 'debug' you can define
    some DTML like so in your manage_main screen::

        <!--#if debug-->
        <p><a href="refresh_docs">Refresh Documents from disk</a></p>
        <!--#/if debug-->

* How do I add management tabs to my folder sub-class?
   
   If you subclass 'OFS.Folder.Folder' to build a folderish object,
   you may want to keep around the old Folder management tabs, but add
   some of your own as well. This can be done by mucking with the
   Folder class 'manage_options' attribute. One problem is that you
   might want your own custom 'manage_main' but the FolderClass uses
   'manage_main' for displaying the contents of the folder. Here is
   what I did for my EMarket product.
   
   By examining Folder's manage_options::
   
       for option in Folder.manage_options:        
           print option 

   We get the following output::

       {'label': 'Contents', 'target': 'manage_main', 'action':
'manage_main'}
       {'label': 'Properties', 'target': 'manage_main', 'action':
'manage_propertiesForm'}
       {'label': 'Import/Export', 'target': 'manage_main', 'action':
'manage_importExportForm'}
       {'label': 'Security', 'target': 'manage_main', 'action':
'manage_access'}
       {'label': 'Undo', 'target': 'manage_main', 'action':
'manage_UndoForm'}
       {'label': 'Find', 'target': 'manage_main', 'action':
'manage_findFrame'}
   
   Notice that the "Contents" tab calls Folder's manage_main attribute.
Just
   rename that in your sub-class with something like::
   
       manage_contents=OFS.Folder.Folder.manage_main
   
   and assign that to a different tab. Here is the beginning of the
MarketItem
   class from the EMarket product::
   
       class MarketItem(OFS.Folder.Folder):
           """A MarketItem """
   
           # Specify a name for the item type:
           meta_type='MarketItem'
   
           # Specify a relative URL for the icon used to display icons:
           icon='misc_/EMarket/marketItem'
           
           # rename Folder's manage_main to manage_contents
           manage_contents=OFS.Folder.Folder.manage_main
  
           manage_main=HTMLFile('marketItemEdit', globals())
           manage_image=HTMLFile('marketItemImage', globals())
   
           # Specify definitions for tabs:
           manage_options=[
               {'label':'Attributes', 'action':'manage_main'},
               {'label':'ImageUpload','action':'manage_image'},
               {'label':'View',       'action':''},
               ]
   
           # add in the options from the Folder class.... change
           # the 'action' for Contents to 'manage_contents' 
           for item in OFS.Folder.Folder.manage_options:
               if item['label'] == 'Contents':
                   # be sure to use a *copy*
                   manage_options.append(item.copy())
                   manage_options[-1]['action'] = 'manage_contents'
               else:
                   manage_options.append(item)