Using repoze.catalog Within Pyramid

repoze.catalog is a ZODB-based system that can be used to index Python objects. It also offers a query interface for retrieving previously indexed data. Those whom are used to Zope’s “ZCatalog” implementation will feel at home using repoze.catalog.

This tutorial assumes that you want a Zope-like setup. For example, it assumes you want to use a persistent ZODB object as your root object, and that the repoze.catalog catalog will be an attribute of this root object. It is further assumed that you want the application to be based on traversal.

  1. Follow the Using ZODB with ZEO tutorial to get a system set up with ZODB and ZEO. When you are finished, come back here.

  2. Install the repoze.catalog software within your application’s environment:

    $ easy_install repoze.catalog
    
  3. Change your ZODB application’s models.py file to look like the below:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    from repoze.folder import Folder
    from repoze.catalog.catalog import Catalog
    from repoze.catalog.document import DocumentMap
    from repoze.catalog.indexes.field import CatalogFieldIndex
    
    def get_title(object, default):
        title = getattr(object, 'title', '')
        if isinstance(title, basestring):
            # lowercase for alphabetic sorting
            title = title.lower()
        return title
    
    class Document(Folder):
        def __init__(self, title):
            self.title = title
            Folder.__init__(self)
    
    class Site(Folder):
        def __init__(self):
            self.catalog = Catalog()
            self.catalog.document_map = DocumentMap()
            self.update_indexes()
            Folder.__init__(self)
    
        def update_indexes(self):
            indexes = {
                'title': CatalogFieldIndex(get_title),
            }
    
            catalog = self.catalog
    
            # add indexes
            for name, index in indexes.iteritems():
                if name not in catalog:
                    catalog[name] = index
    
            # remove indexes
            for name in catalog.keys():
                if name not in indexes:
                    del catalog[name]
    
    def appmaker(root):
        if not 'site' in root:
            root['site'] = Site()
            transaction.commit()
        return root['site']
    
  4. We’ll demonstrate how you might interact with a catalog from code by manipulating the database directly using the pshell command in a terminal window:

    [chrism@snowpro sess]$ ../bin/paster pshell \
           development.ini myapp
    Python 2.5.4 (r254:67916, Sep  4 2009, 02:12:16)
    [GCC 4.2.1 (Apple Inc. build 5646)] on darwin
    Type "help" for more information. "root" is the Pyramid app root.
    >>> from pyramid.traversal import resource_path
    >>> from myapp.models import Document
    >>> root['name'] = Document('title')
    >>> doc = root['name']
    >>> docid = root.catalog.document_map.add(resource_path(doc))
    >>> root.catalog.index_doc(docid, doc)
    >>> import transaction
    >>> transaction.commit()
    >>> root.catalog.search(title='title')
    (1, IFSet([-787959756]))
    

As you need them, add other indexes required by your application to the catalog by modifying the update_indexes method of the Site object. Whenever an index is added or removed, invoke the update_indexes method of the site (the root object) from a script or from within a pshell session to update the set of indexes used by your application.

In view code, you should be able to get a hold of he root object via the pyramid.traversal.find_root() API. The catalog attribute of that root object will represent the catalog previously added.

Read the repoze.catalog documentation for further information about other types of indexes to add, using the document map, and how to issue queries using the catalog query API.

Note

The repoze.folder implementation sends events that can be intercepted by a subscriber when objects are added and removed from a folder. It is often useful to hook these events for the purpose of mutating the catalog when a new documentlike object is added or removed. See the repoze.folder documentation for more information about the events it sends.

Previous topic

Using ZODB with ZEO

Next topic

Debugging