Thanks for the post!

- C

Srikanth T wrote:
> Hi All,
> 
> I want to share a small documentation on , how we cataloged objects in a 
> BFG application (application uses ZODB) .
> 
> *Cataloging objects in BFG*
> 
> One way to catalog the objects in a BFG application is to use subscribers .
> The procedure followed to catalog objects  is :
> 
>    1. Add a catalog file in the root that has a method to catalog the
>       objects.
>    2. In models.py import the catalog method you have written and call
>       it in the appmaker() .
>    3. Implement  zope events interfaces that you require in events.py
>       (you can use any name)
>    4. Then write the functions which you want to execute on firing of
>       above mentioned/decalred events.
>    5. Now use subscriber tag in configure.zcml and register the
>       subscriber function to the events declared.
> 
> Let us see how we can catalog objects.
> 
>     * *catalog.py*
> 
>         Create a python file called catalog.py in the root. Add a method 
> populate_catalog and place the indexes that are required.
> 
>    1. import datetime
>    2. import time
>    3. from zope.interface import providedBy
>    4. from zope.component import queryAdapter
>    5. from zope.interface.declarations import Declaration
>    6. from repoze.bfg.traversal import model_path
>    7. from repoze.bfg.traversal import find_interface
>    8. from repoze.catalog.catalog import Catalog
>    9. from repoze.catalog.indexes.field import CatalogFieldIndex
>   10. from repoze.catalog.indexes.keyword import CatalogKeywordIndex
>   11. from repoze.catalog.indexes.text import CatalogTextIndex
>   12. from repoze.catalog.indexes.path import CatalogPathIndex
>   13. from repoze.catalog.indexes.path2 import CatalogPathIndex2
>   14. from repoze.catalog.document import DocumentMap
>   15. from repoze.bfg.security import principals_allowed_by_permission
>   16. from leavemnt.interfaces import IRoot
>   17. from leavemnt.interfaces import ISearchText
>   18. from leavemnt.interfaces import IVirtualData
>   19. from leavemnt.interfaces import ILeave
>   20. from leavemnt.interfaces import IProfile
>   21. from leavemnt.utils import coarse_datetime_repr
>   22. from leavemnt.utils import find_users
>   23. def get_search_text(object, default):
>   24.     adapter = queryAdapter(object, ISearchText)
>   25.     if adapter is None:
>   26.         return default
>   27.        return adapter()
>   28. def get_creator(object, default):
>   29.     return getattr(object, 'creator', default)
>   30. def _get_date(object, default, name):
>   31.     date = getattr(object, 'modified', None)
>   32.     if date is None:
>   33.         return default
>   34.     # we can't store datetimes directly in the catalog because they
>   35.     # can't be compared with anything
>   36.     timetime = time.mktime(date.timetuple())
>   37.     # creation "minute" actually to prevent too-granular storage
>   38.     date = int(str(int(timetime))[:-2])
>   39.     return date
>   40. def get_modified_date(object, default):
>   41.     return _get_date(object, default, 'modified')
>   42. def get_created_date(object, default):
>   43.     print _get_date(object, default, 'created')
>   44.     return _get_date(object, default, 'created')
>   45. def get_interfaces(object, default):
>   46.     # we unwind all derived and immediate interfaces using
>       spec.flattened()
>   47.     # (providedBy would just give us the immediate interfaces)
>   48.     provided_by = list(providedBy(object))
>   49.     spec = Declaration(provided_by)
>   50.     ifaces = list(spec.flattened())
>   51.     return ifaces
>   52. def get_security_state(obj, default):
>   53.     return getattr(obj, 'security_state', default)
>   54. def populate_catalog(site):
>   55.     catalog = site.catalog   = Catalog()
>   56.     catalog['text'] = CatalogTextIndex(get_search_text)
>   57.     catalog['interfaces'] = CatalogKeywordIndex(get_interfaces)
>   58.     catalog['creator'] = CatalogFieldIndex(get_creator)
>   59.     catalog['modified'] = CatalogFieldIndex(get_modified_date)
>   60.     catalog['created'] = CatalogFieldIndex(get_created_date)
>   61.     catalog['security_state']= CatalogFieldIndex(get_security_state)
>   62.     catalog.document_map = DocumentMap()
>   63. def find_catalog(context):
>   64.     return find_interface(context, IRoot).catalog
> 
>     * *In models.py*
> 
>      In models , import populate_catalog from the catalog.py along with 
> the necessary catalog methods from repoze.catalog .
>      Then in the appmaker function , make a site instance , and pass it 
> as a parameter to the populate_catalog method.
> 
>    1. def appmaker(root):
>    2.     if not root.has_key(SITE_ID):
>    3.         #site = root['site'] = Site()
>    4.         site = Site()
>    5.         root[SITE_ID] = site
>    6.         ## TODO: cleanup catalog creation.
>    7.         populate_catalog(site)
>    8.         leavefolder = LeaveFolder()
>    9.         site['leavefolder'] = leavefolder
>   10.         data = DefaultInitialData()
>   11.         transaction.commit()
>   12.     return root[SITE_ID]
> 
>    Then the site will contain the catalog mechanism. For every 
> subsequent creation, modification and deletion there should be a 
> mechanism to update the catalog.
> 
>     * *subscribers.py  *
> 
>         The following code indexes, reindexes and unindexes on 
> corresponding events.
> 
>    1. import datetime
>    2. from zope.component import queryAdapter
>    3. from repoze.bfg.traversal import model_path
>    4. from repoze.folder.interfaces import IFolder
>    5. from leavemnt.catalog import find_catalog
>    6. from leavemnt.interfaces import IMetadata
>    7. def postorder(startnode):
>    8.     def visit(node):
>    9.         if IFolder.providedBy(node):
>   10.              for child in node.values():
>   11.                  for result in visit(child):
>   12.                      yield result
>   13.         yield node
>   14.     return visit(startnode)
>   15. def index_content(object, event):
>   16.     """ Index content (an IObjectAddedEvent subscriber) """
>   17.     catalog = find_catalog(object)
>   18.     if catalog is not None:
>   19.         for node in postorder(object):
>   20.                 path = model_path(node)
>   21.                 docid = catalog.document_map.add(path)
>   22.                 catalog.index_doc(docid, node)
>   23.                 adapter = queryAdapter(node, IMetadata)
>   24.                 if adapter is not None:
>   25.                     metadata = adapter()
>   26.                     catalog.document_map.add_metadata(docid, metadata)
>   27. def unindex_content(object, event):
>   28.     """ Unindex content (an IObjectWillBeRemovedEvent subscriber) """
>   29.     catalog = find_catalog(object)
>   30.     if catalog is not None:
>   31.         path = model_path(object)
>   32.         num, docids = catalog.search(path=path)
>   33.         for docid in docids:
>   34.             catalog.unindex_doc(docid)
>   35.             catalog.document_map.remove_docid(docid)
>   36. def reindex_content(object, event):
>   37.     """ Reindex a single piece of content (non-recursive); an
>   38.     IObjectModifed event subscriber """
>   39.     catalog = find_catalog(object)
>   40.     if catalog is not None:
>   41.         path = model_path(object)
>   42.         docid = catalog.document_map.docid_for_address(path)
>   43.         catalog.reindex_doc(docid, object)
>   44.         #catalog.document_map.remove_metadata(docid)
>   45.         adapter = queryAdapter(object, IMetadata)
>   46.         if adapter is not None:
>   47.             metadata = adapter()
>   48.             catalog.document_map.add_metadata(docid, metadata)
>   49.         
>   50. def set_modified(object, event):
>   51.     """ Set the modified date on a single piece of content
>   52.     unconditionally (non-recursive); an IObjectModified event
>   53.     subscriber"""
>   54.     now = datetime.datetime.now()
>   55.     object.modified = now
>   56. def set_created(object, event):
>   57.     """ Add modified and created attributes to nodes which do not yet
>   58.     have them (recursively); an IObjectWillBeAddedEvent subscriber"""
>   59.     now = datetime.datetime.now()
>   60.     for node in postorder(object):
>   61.             if not getattr(node, 'modified', None):
>   62.                 node.modified = now
>   63.             if not getattr(node, 'created', None):
>   64.                 node.created = now
> 
>    When ever the event subscribed in configure.zcml is fired, approriate 
> methods (in subscribers.py) is called.
> 
>     * *configure.zcml*
> 
>        In configure.zcml, make a subscriber tag and define the 
> corresponding handlers, for an event.
> 
>    1. <configure xmlns="http://namespaces.repoze.org/bfg";>
>    2.   <!-- this must be included for the view declarations to work -->
>    3.   <include package="repoze.bfg.includes" />
>    4.   <include package="leavemnt.security_policies" />
>    5.   <include package="leavemnt.views" />
>    6.   <!--scan package="."/-->
>    7.   <static
>    8.     name="static"
>    9.     path="templates/static"
>   10.     />
>   11.     
>   12.   <subscriber
>   13.       for="leavemnt.interfaces.ILeave
>   14.            repoze.folder.interfaces.IObjectWillBeRemovedEvent"
>   15.       handler=".subscribers.unindex_content" />
>   16.     
>   17.   <subscriber
>   18.       for="leavemnt.interfaces.ILeave
>   19.            repoze.folder.interfaces.IObjectAddedEvent"
>   20.       handler=".subscribers.index_content" />
>   21.   <subscriber
>   22.       for="leavemnt.interfaces.ILeave
>   23.            .interfaces.IObjectModifiedEvent"
>   24.       handler=".subscribers.reindex_content" />
>   25.   <subscriber
>   26.       for="*
>   27.            repఅవును oze.folder.interfaces.IObjectWillBeAddedEvent"
>   28.       handler=".subscribers.set_created" />
>   29.   <subscriber
>   30.       for="leavemnt.interfaces.IProfile
>   31.            repoze.folder.interfaces.IObjectWillBeRemovedEvent"
>   32.       handler=".subscribers.unindex_content" />
>   33.     
>   34.   <subscriber
>   35.       for="leavemnt.interfaces.IProfile
>   36.            repoze.folder.interfaces.IObjectAddedEvent"
>   37.       handler=".subscribers.index_content" />
>   38.   <subscriber
>   39.       for="leavemnt.interfaces.IProfile
>   40.            .interfaces.IObjectModifiedEvent"
>   41.       handler=".subscribers.reindex_content" />
>   42.   <subscriber
>   43.       for="*
>   44.            .interfaces.IObjectModifiedEvent"
>   45.       handler=".subscribers.set_modified" />
>   46. </configure>
> 
>     * *events.py*
> 
>         in events.py define the events as required.
> 
>    1. from leavemnt.interfaces import IObjectModifiedEvent
>    2. from leavemnt.interfaces import IObjectWillBeModifiedEvent
>    3. from zope.interface import implements
>    4. class ObjectModifiedEvent(object):
>    5.     implements(IObjectModifiedEvent)
>    6.     def __init__(self, object):
>    7.         print  object
>    8.         self.object = object
>    9. class ObjectWillBeModifiedEvent(object):
>   10.     implements(IObjectWillBeModifiedEvent)
>   11.     def __init__(self, object):
>   12.         self.object = object
> 
> -- 
> Thanks & Regards,
> Srikanth.T
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Repoze-dev mailing list
> Repoze-dev@lists.repoze.org
> http://lists.repoze.org/listinfo/repoze-dev

_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev

Reply via email to