.. _schema-ref:

Schema Reference
================

.. module:: simplecouchdb.schema

The Document interface
----------------------

An application describes the kinds of data it uses with :ref:`document-ref`. A document is a Python class that inherits from the :class:`simplecouchdb.schema.Document` class. The document class defines a new kind of CouchDB document and the properties the kind is expected to take.

Document properties are defined using class attributes on the document class. Each class attribute is an instance of a subclass of the Property class, usually one of the provided property classes. A property instance holds configuration for the property, such as whether or not the property is required for the instance to be valid, or a default value to use for the instance if none is provided.

.. code-block:: python

    from simplecouchdb import schema

    class Pet(schema.Document):
        name = schema.StringProperty(required=True)
        type = schema.StringProperty(required=True)
        birthdate = schema.DateProperty()
        weight_in_pounds = schema.IntegerProperty()
        spayed_or_neutered = schema.BooleanProperty()
        owner = schema.StringProperty()

An CouchDB document is represented in the API by an instance of the corresponding document class. The application can create a new document by calling the constructor of the class. The application accesses and manipulates properties of the entity using attributes of the instance. The document instance constructor accepts initial values for properties as keyword arguments.

.. code-block:: python

    pet = Pet(name="Fluffy",
          type="cat",
          owner="Jean")
    pet.weight_in_pounds = 24

.. note::

    The attributes of the document class are configuration for the model properties, whose values are :class:`simplecouchdb.schema.Property` instances. The attributes of the document instance are the actual property values, whose values are of the type accepted by the Property class.

The document class use the Property instances to validate data. The validation could occur when you validate(:meth:`simplecouchdb.Document.validate`) the document class or save (:meth:`simplecouchdb.Document.save`) it.

An instance of a model created using the constructor does not exist in the datastore until it is "saved" for the first time. See :ref:`creating-getting-deleting-ref`.

Document is dynamic
--------------------

Sometimes it is usefull to have different properties on each document. CouchDB allow it so why not having it in python. A document can have both dynamic and static property. Any value assigned to an attribute of an instance of a document becomes a property of the CouchDB document, using the name of the attribute. These properties are known as dynamic properties. Properties defined using Property class instances in class attributes are fixed properties.

.. code-block:: python

    class Person(schema.Document):
        first_name = schema.StringProperty()
        last_name = schema.StringProperty()
        hobbies = schema.ListProperty()

    p = Person(first_name="Albert", last_name="Johnson")
    p.hobbies = ["chess", "travel"]

    p.chess_elo_rating = 1350

    p.travel_countries_visited = ["Spain", "Italy", "USA", "Brazil"]
    p.travel_trip_count = 13

Because dynamic properties do not have document property definitions, dynamic properties are not validated. Any dynamic property can have a value of any of the python types, including None. 

Unlike fixed properties, dynamic properties need not exist. A dynamic property with a value of None is different from a non-existent dynamic property.  You can delete a dynamic property by deleting the attribute.

.. code-block:: python
    
    del p.chess_elo_rating

A request that uses a dynamic property will only return entities whose value for the property is of the same type as the value used in the request. Similarly, the request will only return entities with that property set.

.. code-block:: python

    p1 = Person()
    p1.favorite = 42
    p1.save(db)

    p2 = Person()
    p2.favorite = "blue"
    p2.save(db)

    p3 = Person()
    p3.save(db)

    people = Person.view(db, "person/favorite", startkey=0, endkey=50)
    # people has p1, but not p2 or p3

    people = Person.view(db, "person/favorite")", startkey=50)
    # people has no results

.. note::

    Some dynamic data in couchdb are automatically converted to their python type. Those are datetime, datetime.date, datetime.time and Decimal types. this is only possible if date/time fields are :rfc:`8601` strings in the couchdb document.

Document inheritance
--------------------

Document inheritance in simplecouchdb work almost identically to the way normal class inheritance works in Python. The only difference is that you can't inherit views.

.. code-block:: python

    class Animal(Document)
        name = schema.StringProperty(required=True)
        type = schema.StringProperty(required=True)

    class Pet(Animal):
        birthdate = schema.DateProperty()
        weight_in_pounds = schema.IntegerProperty()
        spayed_or_neutered = schema.BooleanProperty()
        owner = schema.StringProperty()

The :class:`Pet` document will have 6 properties name, type, birthdate, weight_in_pounds, spayed_or_neutered, owner. It can be used as a common Document object. Pet and Animal have 2 different doc_type.

.. note::

    For now, there is no way in CouchDB to know that Pet inherit from Animal. Though this feature will be implemented soon.
 

Properties and Types
--------------------

Couchdb support all Javascrip types, including Unicode strings, integers, floating point numbers. We also added support for dates and decimal types. Each of the CouchDB value type has a corresponding Property class provided by the :mod:`simplecouchdb.schema` module.

:ref:`property-ref` describes all of the supported value types and their corresponding Property classes. 

Reference
---------

.. toctree::
   :maxdepth: 2

   creating_getting_deleting
   document
   property 
