Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

I think I've seen this ORM somewhere before...

root/trunk/doc/intro.html

Revision 23 (checked in by fumanchu, 9 years ago)

Oops. Shouldn't have add xray, recur. Better without.

Line 
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2    "http://www.w3.org/TR/xhtml1/DTD/strict.dtd">
3 <html xmlns="http://www.w3.org/TR/xhtml1/strict" xml:lang="en" lang="en">
4
5 <head>
6     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
7     <title>Dejavu: Introduction</title>
8     <link href='dejavu.css' rel='stylesheet' type='text/css' />
9 </head>
10
11 <body>
12
13 <h2>Introduction</h2>
14
15 <p>Dejavu is an Object-Relational Mapper for Python applications. It is
16 designed to provide the "Model" third of an MVC application. When you build
17 an application using Dejavu, you must supply the Controller(s) and View(s)
18 yourself. Dejavu does not provide these, and does its best to not limit
19 your choices regarding them.</p>
20
21 <p>If you're familiar with Martin Fowler's work <a href='#fowler'>[1]</a>,
22 you can think of Dejavu as providing a Data Source layer, plus the tools
23 to write your own Domain layer. For the Presentation layer, you're on your
24 own. ;)</p>
25
26 <h3>Basic Structure</h3>
27 <p>Developers build their Model (or <i>schema</i>) by creating classes
28 which subclass the <tt>Unit</tt> class; for those of you stuck in RDBMS
29 mindsets, each Unit subclass corresponds to a table; instances of the class
30 correspond to the rows. Each subclass possesses a set of attributes known
31 as "properties", which you can think of as columns in your database
32 table. These attributes are generally formed from a <tt>UnitProperty</tt>
33 descriptor. Any Unit data which needs to be persisted ought to be contained
34 in a Unit property. However, Unit classes can also possess arbitrary
35 methods and attributes which aid their use within the application.</p>
36
37 <p>Unit classes can be <i>associated</i> to other Unit classes. This means
38 that one of the properties of UnitA maps to one of the properties of UnitB.
39 Related objects may then be looked up more easily.</p>
40
41 <p>Units are managed in memory by <tt>Sandbox</tt> objects, which function
42 as "Identity Maps" <a href='#fowler'>[1]</a>; in-memory caches of Units
43 which keep commit conflicts to a minimum. Unit objects can be "memorized"
44 and "recalled" from a <tt>Sandbox</tt>, using pure Python lambda expressions
45 <a href='#cpython'>[2]</a> as a query language. The lambda is wrapped
46 in an <tt>Expression</tt> object to make it portable.</p>
47
48 <p>Sandboxes persist Unit data by <tt>StorageManager</tt> objects. Each
49 persistence mechanism has its own subclass of the <tt>StorageManager</tt>
50 class; for example, persisting Unit data to a Microsoft SQL Server database
51 requires a <tt>StorageManagerADO_SQLServer</tt> object. When recalling data,
52 Storage Managers receive Expression objects; database SM's, for example,
53 will typically examine these Expressions and produce SQL statements from
54 them, which they then use to retrieve data. Storage Managers also handle
55 the creation of new Units, and their destruction.</p>
56
57 <p>Finally, Dejavu provides a core <tt>Arena</tt> class which you should be
58 able to leverage for any sort of application you are building. The Arena
59 object functions as a top-level "Application" object, collecting the global
60 settings for an application into one place. It doles out Sandboxes,
61 maintains a registry of Units and their associations, and manages startup
62 and shutdown operations.</p>
63
64
65 <h3>Simple Example</h3>
66
67 <p>Since a block of code is often worth a thousand words, here's a minimal
68 example of a Dejavu application:</p>
69
70 zookeeper.py
71 <pre>import dejavu
72 from dejavu.storage.storeado import StorageManagerADO_MSAccess as SM
73
74 # Set up a global Arena object.
75 arena = dejavu.Arena()
76 conf = {u'Connect':
77         r"PROVIDER=MICROSOFT.JET.OLEDB.4.0;DATA SOURCE=C:\zookeeper.mdb;"}
78 arena.add_store('main', SM("mySM", arena, conf))
79
80
81 class Zoo(dejavu.Unit):
82     Name = dejavu.UnitProperty('Name', unicode)
83     Size = dejavu.UnitProperty('Size', int)
84    
85     def total_legs(self):
86         return sum([x.Legs for x in self.Animal()])
87
88 class Animal(dejavu.Unit): pass
89 Animal.set_properties({"Name": unicode,
90                         "Legs": int,
91                         "ZooID": int,
92                         })
93 arena.associate(Zoo, 'ID', Animal, 'ZooID')</pre>
94
95 <p>The above creates the model/schema for the zookeeper application.
96 There are three basic things happening:
97     <ol>
98         <li>The <tt>Zoo</tt> and <tt>Animal</tt> classes, which subclass
99             <tt>dejavu.Unit</tt>. These will correspond to the Zoo and
100             Animal tables within the database. Notice the two different
101             methods of setting Unit properties. Each class also inherits
102             an 'ID' property (an int) from <tt>dejavu.Unit</tt>.</li>
103         <li>The setup of a dejavu <tt>Arena</tt> object, including a Storage
104             Manager which uses a Microsoft Access (Jet) database.</li>
105         <li>The association between the Zoo class and the Animal class.</li>
106     </ol>
107 </p>
108
109 <p>Here's a simple interactive session which uses the above:</p>
110
111 <pre>>>> import zookeeper
112 >>> box = zookeeper.arena.new_sandbox()
113 >>> [x for x in box.recall(zookeeper.Animal)]
114 [&lt;zookeeper.Animal object at 0x013281F0>, &lt;zookeeper.Animal object at 0x01328150>,
115  &lt;zookeeper.Animal object at 0x01328130>, &lt;zookeeper.Animal object at 0x01328230>]
116 >>> [x for x in box.recall(zookeeper.Zoo)]
117 []
118 >>> zoo = zookeeper.Zoo(Name='San Diego Zoo', Size='38')
119 >>> box.memorize(zoo)
120 >>> zoo.ID
121 1
122 >>> box.unit(zookeeper.Zoo, ID=1) is zoo
123 True
124 >>> for creature in box.recall(zookeeper.Animal):
125         zoo.add(creature)
126 >>> len(list(zoo.Animal()))
127 4</pre>
128
129
130 <h3>Design Goals</h3>
131
132 <p>Dejavu is designed to function in environments with complex integration
133 needs, and tends to separate concerns as much as possible. In particular,
134 Dejavu tries to avoid making decisions in the framework which are better
135 left to developers. Some of those decisions are:
136     <ul>
137         <li>Which interface style to use.</li>
138         <li>Application package architecture. You can place your application
139             within a single Python module, or develop complete packages.</li>
140         <li>Which types to use for <tt>Unit</tt> properties.</li>
141         <li>Which keys to use when associating <tt>Unit</tt> classes.</li>
142     </ul>
143
144 In the same way, Dejavu tries to avoid having developers make decisions
145 which are better left to deployers. Some of those decisions are:
146     <ul>
147         <li>How to specify configuration data. Dejavu is equally happy
148             obtaining configs from Python dictionaries, .ini files,
149             or XML files. Additional methods are easy to develop.</li>
150         <li>Where (and how) to log messages.</li>
151         <li>Which storage mechanism (database or ...?) to use. In particular,
152             deployers are allowed to mix and match stores, including how
153             and when to cache objects in memory. Dejavu tries to make
154             it easy for <i>deployers</i> to tune applications to their
155             particular environment.</li>
156     </ul>
157 </p>
158
159 <p>In particular, Dejavu was designed to make complex integration easier.
160 Unlike most generic storage wrappers, Dejavu does not <i>require</i> you to
161 have complete control of your back end. For example, consider Mission
162 Control, the first application built on Dejavu. Mission Control required
163 an ORM which transparently supported two very different backends. Half of
164 the data was to be stored in an MS Access database (which is being migrated
165 to SQL Server), over which the application developers had full control.
166 But half of the data was stored in a third-party application, "The Raiser's
167 Edge" (RE) from Blackbaud. RE provides read-only database access; all writes
168 must go through their object-oriented API. Further, reading via that API was
169 found to be too slow. Therefore, a custom Storage Manager (about 2500 lines
170 of code) was developed, which searches for and loads objects via SQL, but
171 writes Unit data via the REAPI. Dejavu allows the application logic to be
172 completely ignorant of this complex mass of storage details. If Blackbaud
173 closed its doors tomorrow, the solution could be quickly migrated to another
174 data store; business downtime is reduced in the face of inevitable change.<p>
175
176 <h3>Obtaining and Installing</h3>
177
178 <p>You can obtain Dejavu from its Subversion repository at
179 <tt>svn://casadeamor.com/dejavu/trunk</tt>. Dejavu expects to be
180 installed in <tt>site-packages/dejavu</tt>.</p>
181
182 <p>Dejavu depends upon two additional libraries, <tt>recur.py</tt> and
183 <tt>xray.py</tt>, which are available at <tt>svn://casadeamor.com/misc</tt>.
184 You need to place these two modules in your site-packages directory.</p>
185
186 <p>Dejavu was built using Python 2.3.2. You should probably use
187 at least 2.3; Dejavu depends upon the <tt>datetime</tt> module.
188 Although Dejavu <i>supports</i> additional modules like
189 <tt>fixedpoint</tt> and <tt>decimal</tt>, it does not <i>require</i>
190 them.</p>
191
192 <p>Dejavu uses bytecode hacks, and therefore requires CPython
193 <a href='#cpython'>[2]</a>.</p>
194
195 <h3>Compared To Other Database Wrappers</h3>
196 <p>TBW</p>
197
198 <hr />
199
200 <p><a name='fowler'>[1]</a> Fowler,
201 <a href='http://www.martinfowler.com/eaaCatalog/identityMap.html'>Patterns
202 of Enterprise Application Architecture</a>.<br />
203 <a name='cpython'>[2]</a> Dejavu relies upon bytecode hacking to achieve
204 its clean lambda syntax for data queries. Therefore, it is CPython-specific.
205 In addition, the bytecode of Python may change from one version of Python
206 to another; if you find your version of Python does not work with Dejavu's
207 <tt>codewalk</tt> and <tt>logic</tt> modules, please let me know.<br />
208 </p>
209
210 </body>
211 </html>
Note: See TracBrowser for help on using the browser.