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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
.. _catalog_tutorial:
Using :mod:`repoze.catalog` Within :app:`Pyramid`
=================================================
:mod:`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 :mod:`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
:term:`root` object, and that the :mod:`repoze.catalog` catalog will
be an attribute of this root object. It is further assumed that you
want the application to be based on :term:`traversal`.
#. Follow the :ref:`zodb_with_zeo` tutorial to get a system set up
with ZODB and ZEO. When you are finished, come back here.
#. Install the :mod:`repoze.catalog` software within your application's
environment:
.. code-block:: text
$ easy_install repoze.catalog
#. Change your ZODB application's ``models.py`` file to look like the
below:
.. code-block:: python
:linenos:
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']
#. 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:
.. code-block:: text
[chrism@snowpro sess]$ ../bin/paster --plugin=pyramid 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 object.
>>> from pyramid.traversal import model_path
>>> from myapp.models import Document
>>> root['name'] = Document('title')
>>> doc = root['name']
>>> docid = root.catalog.document_map.add(model_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 :term:`view` code, you should be able to get a hold of he root
object via the :func:`pyramid.traversal.find_root` API. The
``catalog`` attribute of that root object will represent the catalog
previously added.
Read the :mod:`repoze.catalog` `documentation
<http://docs.repoze.org/catalog>`_ 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 :mod:`repoze.folder` implementation sends events that can be
intercepted by a :term:`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
<http://docs.repoze.org/folder>`_ for more information about the
events it sends.
|