Package couchdbkit :: Package schema
[hide private]
[frames] | no frames]

Source Code for Package couchdbkit.schema

  1  # -*- coding: utf-8 - 
  2  # 
  3  # This file is part of couchdbkit released under the MIT license. 
  4  # See the NOTICE for more information. 
  5   
  6  """\ 
  7  Schema is an easy way to map couchdb object in pythoin object. It's 
  8  similar to ORMs but with all couchdb glory. 
  9   
 10  An application describes the kinds of data it uses with a Document object. A 
 11  document is a Python class that inherits from the `couchdbkit.schema.Document` 
 12  class. The document class defines a new kind of CouchDB document and the 
 13  properties the kind is expected to take. 
 14   
 15  Document properties are defined using class attributes on the document class. 
 16  Each class attribute is an instance of a subclass of the Property class, 
 17  usually one of the provided property classes. A property instance holds 
 18  configuration for the property, such as whether or not the property is required 
 19  for the instance to be valid, or a default value to use for the instance if 
 20  none is provided. 
 21   
 22   
 23      from couchdbkit import Document 
 24   
 25      class Pet(Document): 
 26          name = schema.StringProperty(required=True) 
 27          type = schema.StringProperty(required=True) 
 28          birthdate = schema.DateProperty() 
 29          weight_in_pounds = schema.IntegerProperty() 
 30          spayed_or_neutered = schema.BooleanProperty() 
 31          owner = schema.StringProperty() 
 32   
 33  An CouchDB document is represented in the API by an instance of the 
 34  corresponding document class. The application can create a new document by 
 35  calling the constructor of the class. The application accesses and manipulates 
 36  properties of the entity using attributes of the instance. The document 
 37  instance constructor accepts initial values for properties as keyword 
 38  arguments. 
 39   
 40   
 41      pet = Pet(name="Fluffy", 
 42            type="cat", 
 43            owner="Jean") 
 44      pet.weight_in_pounds = 24 
 45   
 46   
 47  Document is dynamic 
 48  ------------------- 
 49   
 50  Sometimes it is usefull to have different properties on each document. CouchDB 
 51  allows it, so why not having it in python. A document can have both dynamic and 
 52  static property. Any value assigned to an attribute of an instance of a 
 53  document becomes a property of the CouchDB document, using the name of the 
 54  attribute. These properties are known as dynamic properties. Properties defined 
 55  using Property class instances in class attributes are fixed properties. 
 56   
 57   
 58      class Person(Document): 
 59          first_name = schema.StringProperty() 
 60          last_name = schema.StringProperty() 
 61          hobbies = schema.ListProperty() 
 62   
 63      p = Person(first_name="Albert", last_name="Johnson") 
 64      p.hobbies = ["chess", "travel"] 
 65   
 66      p.chess_elo_rating = 1350 
 67   
 68      p.travel_countries_visited = ["Spain", "Italy", "USA", "Brazil"] 
 69      p.travel_trip_count = 13 
 70   
 71  Because dynamic properties do not have document property definitions, dynamic 
 72  properties are not validated. Any dynamic property can have a value of any of 
 73  the python types, including None. 
 74   
 75  Unlike fixed properties, dynamic properties need not exist. A dynamic property 
 76  with a value of None is different from a non-existent dynamic property.  You 
 77  can delete a dynamic property by deleting the attribute. 
 78   
 79      del p.chess_elo_rating 
 80   
 81  A request that uses a dynamic property will only return entities whose value 
 82  for the property is of the same type as the value used in the request. 
 83  Similarly, the request will only return entities with that property set. 
 84   
 85   
 86      p1 = Person() 
 87      p1.favorite = 42 
 88      db.save_doc(p1) 
 89   
 90      p2 = Person() 
 91      p2.favorite = "blue" 
 92      db.save_doc(p2) 
 93   
 94      p3 = Person() 
 95      db.save_doc(p3) 
 96   
 97      people = Person.view(db, "person/favorite", startkey=0, endkey=50) 
 98      # people has p1, but not p2 or p3 
 99   
100      people = Person.view(db, "person/favorite")", startkey=50) 
101      # people has no results 
102   
103   
104  Some dynamic data in couchdb are automatically converted to their python type. 
105  Those are datetime, datetime.date, datetime.time and Decimal types. this is 
106  only possible if date/time fields are :rfc:`8601` strings in the couchdb 
107  document. 
108   
109  Document inheritance in simplecouchdb work almost identically to the way normal 
110  class inheritance works in Python. 
111   
112      class Animal(Document) 
113          name = StringProperty(required=True) 
114          type = StringProperty(required=True) 
115   
116      class Pet(Animal): 
117          birthdate = DateProperty() 
118          weight_in_pounds = IntegerProperty() 
119          spayed_or_neutered = BooleanProperty() 
120          owner = StringProperty() 
121   
122  The `Pet` document will have 6 properties name, type, birthdate, 
123  weight_in_pounds, spayed_or_neutered, owner. It can be used as a common 
124  Document object. Pet and Animal have 2 different doc_type. 
125   
126  For now, there is no way in CouchDB to know that Pet inherit from Animal. 
127  Though this feature will be implemented soon. 
128   
129   
130  Properties and Types 
131  -------------------- 
132   
133  Couchdb supports all Javascript types, including Unicode strings, integers, 
134  floating point numbers. We also added support for dates and decimal types. Each 
135  of the CouchDB value type has a corresponding Property class provided by the 
136  :mod:`simplecouchdb.schema` module. 
137   
138   
139  Other way to save on the db. 
140  ---------------------------- 
141   
142  If you don't want to use the db object to save doc each time and save 
143  àla "ORM" you can fix a db to a Document class:: 
144   
145      class A(Dcoument): 
146          s = StringProperty() 
147   
148      A.set_db(db) 
149   
150      a = A() 
151      a.save() 
152   
153  This method isn't really threadsafe since once class will share a db 
154  reference across threads, changing a db to a class will be applied to 
155  all threads. It's better to use the db object methods if you want to be 
156  threadsafe. 
157  """ 
158   
159  from .properties import ( 
160          ALLOWED_PROPERTY_TYPES, 
161          Property, 
162          StringProperty, 
163          IntegerProperty, 
164          DecimalProperty, 
165          BooleanProperty, 
166          FloatProperty, 
167          DateTimeProperty, 
168          DateProperty, 
169          TimeProperty, 
170          DictProperty, 
171          ListProperty, 
172          StringListProperty, 
173          SetProperty, 
174          dict_to_json, 
175          list_to_json, 
176          value_to_json, 
177          MAP_TYPES_PROPERTIES, 
178          value_to_python, 
179          dict_to_python, 
180          list_to_python, 
181          convert_property, 
182          value_to_property, 
183          LazyDict, 
184          LazyList) 
185   
186  try: 
187      from .properties import SetProperty, LazySet 
188  except ImportError: 
189      pass 
190   
191  from .base import ( 
192          ReservedWordError, 
193          ALLOWED_PROPERTY_TYPES, 
194          DocumentSchema, 
195          SchemaProperties, 
196          DocumentBase, 
197          QueryMixin, 
198          AttachmentMixin, 
199          Document, 
200          StaticDocument, 
201          valid_id) 
202   
203  from .properties_proxy import ( 
204          SchemaProperty, 
205          SchemaListProperty, 
206          SchemaDictProperty) 
207   
208 -def contain(db, *docs):
209 """ associate a db to multiple `Document` class""" 210 for doc in docs: 211 if hasattr(doc, '_db'): 212 doc._db = db
213