The pouchdb.mapping module

Mapping from raw JSON data structures to Python objects and vice versa.

While this module is partly based on couchdb.mapping, it doesn’t try to provide the exact same API. The largest differences can be found in the DictField class, the ListField class, the Document.query() method and the fact that there’s no Mapping class.

Examples on how to use this module:

>>> env = setup()
>>> db = env.PouchDB('python-tests')

To define a document mapping, you declare a Python class inherited from Document, and add any number of Field attributes:

>>> from datetime import datetime
>>> from pouchdb.mapping import Document, TextField, IntegerField, DateTimeField
>>> 
>>> class Person(Document):
...     name = TextField()
...     age = IntegerField()
...     added = DateTimeField(default=datetime.now)
... 
>>> person = Person(name='John Doe', age=42)
>>> person.store(db) 
Person(added=datetime.datetime(...), age=42, name='John Doe')
>>> person.age
42

You can then load the data from the CouchDB server through your Document subclass, and conveniently access all attributes:

>>> person = Person.load(db, person.id)
>>> old_rev = person.rev
>>> print person.name
John Doe
>>> person.age
42
>>> person.added                
datetime.datetime(...)

To update a document, simply set the attributes, and then call the Document.store() method:

>>> person.name = 'John R. Doe'
>>> person.store(db)            
Person(added=datetime.datetime(...), age=42, name='John R. Doe')

If you retrieve the document from the server again, you should be getting the updated data:

>>> person = Person.load(db, person.id)
>>> print person.name
John R. Doe
>>> person.rev != old_rev
True
>>> env.destroy('python-tests')

API

class pouchdb.mapping.Document(_jsonSource=False, **values)[source]

The document class by default already has two defined fields: id and rev. They’re used to determine the values of CouchDB’s and PouchDB’s _id and _rev special attributes.

as_dict[source]

Returns the fields with their values in the form of a dict.

>>> class Post(Document):
...     title = TextField()
...     author = TextField()
>>> post = Post(id='foo-bar', title='Foo bar', author='Joe')
>>> printjson(post.as_dict)
{"_id": "foo-bar", "author": "Joe", "title": "Foo bar"}
classmethod load(db, id)[source]

Load a specific document from the given database.

Parameters:
  • db – the Database object to retrieve the document from
  • id – the document ID
Returns:

the Document instance

Raises pouchdb.PouchDBError:
 

when the document with id can’t be found.

classmethod query(db, info, **options)[source]

Same as pouchdb.AbstractPouchDB.query(), but replaces each row with an instance of (your subclass of) Document. Additional attributes set on these objects are key and value. Sets options["include_docs"] to True (otherwise the mapping doesn’t make any sense). Except when there’s a reduce function, in that case no mapping takes place at all.

store(db)[source]

Store the document in the given database.

Field types

Complex field types

class pouchdb.mapping.ViewField(design, map_fun, reduce_fun=None, name=None, language='javascript', **defaults)[source]

Descriptor that can be used to bind a view definition to a property of a Document class.

>>> from pouchdb.mapping import TextField, IntegerField, ViewField
>>> class Person(Document):
...     name = TextField()
...     age = IntegerField()
...     by_name = ViewField('people', '''\
...         function(doc) {
...             emit(doc.name, doc);
...         }''')
>>> Person.by_name
<ViewField 'people'>
>>> print Person.by_name.map_fun
        function(doc) {
            emit(doc.name, doc);
        }

That property can be used as a function, which will execute the view.

>>> db = setup().PouchDB('python-tests')
>>> Person(name='test').store(db)
Person(name='test')
>>> printjson(Person.by_name(db, limit=3))
{"offset": 0, "rows": ["Person(name='test')"], "total_rows": 1}

The results produced by the view are automatically wrapped in the Document subclass the descriptor is bound to. In this example, it returns instances of the Person class. This can be done because the ViewField automatically includes the include_docs option when making a query. See for more info the Document.query() method.

If you use Python view functions, this class can also be used as a decorator:

>>> class Person(Document):
...     name = TextField()
...     age = IntegerField()
...
...     @ViewField.define('people')
...     def by_name(doc):
...             yield doc['name'], doc
>>> Person.by_name
<ViewField 'people'>
>>> print Person.by_name.map_fun
def by_name(doc):
        yield doc['name'], doc
class pouchdb.mapping.DictField(name=None, default=None, jsonSerializable=None, toPy=None)[source]

Field type for nested dictionaries.

>>> from pouchdb.mapping import DictField
>>> db = setup()['python-tests']
>>> class Post(Document):
...     title = TextField()
...     content = TextField()
...     author = DictField()
...     extra = DictField()
>>> post = Post(
...     title='Foo bar',
...     author=dict(name='John Doe',
...                 email='john@doe.com'),
...     extra=dict(foo='bar'),
... )
>>> post.store(db)
Post(author={'email': 'john@doe.com', 'name': 'John Doe'}, extra={'foo': 'bar'}, title='Foo bar')
>>> post = Post.load(db, post.id)
>>> print post.author.name
John Doe
>>> print post.author.email
john@doe.com
>>> printjson(post.extra)
{"foo": "bar"}
>>> printjson(db.destroy())
{"ok": true}
class pouchdb.mapping.ListField(name=None, default=None, jsonSerializable=None, toPy=None)[source]

Field type for sequences of other fields.

>>> from pouchdb.mapping import ListField
>>> import dateutil.parser
>>> import copy
>>> db = setup()["python-tests"]
>>> 
>>> def load(rows):
...     for row in rows:
...         row["time"] = dateutil.parser.parse(row["time"])
...     return rows
... 
>>> def serialize(input):
...     rows = copy.deepcopy(input)
...     for row in rows:
...         row["time"] = row["time"].isoformat()
...     return rows
... 
>>> class Post(Document):
...     title = TextField()
...     content = TextField()
...     pubdate = DateTimeField(default=datetime.now)
...     comments = ListField(jsonSerializable=serialize, toPy=load)
... 
>>> post = Post(title='Foo bar')
>>> post.comments.append(dict(author='myself', content='Bla bla',
...                      time=datetime.now()))
>>> len(post.comments)
1
>>> post.store(db) 
Post(...)
>>> post = Post.load(db, post.id)
>>> comment = post.comments[0]
>>> print comment['author']
myself
>>> print comment['content']
Bla bla
>>> comment['time'] 
datetime.datetime(...)
>>> printjson(db.destroy())
{"ok": true}

Simple field types

class pouchdb.mapping.BooleanField(name=None, default=None)[source]

Mapping field for boolean values.

class pouchdb.mapping.DateField(name=None, default=None)[source]

Mapping field for date values.

class pouchdb.mapping.DateTimeField(name=None, default=None)[source]

Mapping field for date/time values.

class pouchdb.mapping.DecimalField(name=None, default=None)[source]

Mapping field for decimal values.

class pouchdb.mapping.FloatField(name=None, default=None)[source]

Mapping field for float values.

class pouchdb.mapping.IntegerField(name=None, default=None)[source]

Mapping field for integer values.

class pouchdb.mapping.LongField(name=None, default=None)[source]

Mapping field for long values.

class pouchdb.mapping.TextField(name=None, default=None)[source]

Mapping field for float values.

class pouchdb.mapping.TimeField(name=None, default=None)[source]

Mapping field for time values.

Table Of Contents

Previous topic

The pouchdb.objectstorage module

Next topic

The pouchdb.tests package

This Page