[Checkins] SVN: megrok.rdb/trunk/src/megrok/rdb/ Add (incomplete) support for QueryContainer, a container driven by
Martijn Faassen
faassen at infrae.com
Wed Aug 20 13:42:49 EDT 2008
Log message for revision 90035:
Add (incomplete) support for QueryContainer, a container driven by
a custom query.
Changed:
U megrok.rdb/trunk/src/megrok/rdb/README.txt
U megrok.rdb/trunk/src/megrok/rdb/__init__.py
U megrok.rdb/trunk/src/megrok/rdb/components.py
-=-
Modified: megrok.rdb/trunk/src/megrok/rdb/README.txt
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/README.txt 2008-08-20 17:13:59 UTC (rev 90034)
+++ megrok.rdb/trunk/src/megrok/rdb/README.txt 2008-08-20 17:42:48 UTC (rev 90035)
@@ -266,3 +266,64 @@
Quantum Mechanics Quantum Mechanics Physics
Relativity Relativity Physics
+Custom query container
+----------------------
+
+Sometimes we want to expose objects as a (read-only) container based
+on a query, not a relation. This is useful when constructing an
+application and you need a "starting point", a root object that
+launches into SQLAlchemy-mapped object that itself is not directly
+managed by SQLAlchemy.
+
+We can construct such a special container by subclassing from ``rdb.QueryContainer`` and implementing
+the special ``query`` method::
+
+ >>> class MyQueryContainer(rdb.QueryContainer):
+ ... def query(self):
+ ... return session.query(Department)
+ >>> qc = MyQueryContainer()
+
+Let's try some common read-only container operations, such as
+``__getitem__``1::
+
+ >>> qc[1].name
+ u'Philosophy'
+ >>> qc[2].name
+ 'Physics'
+
+XXX Why the unicode difference?
+
+``__getitem__`` with a ``KeyError``::
+
+ >>> qc[3]
+ Traceback (most recent call last):
+ ...
+ KeyError: 3
+
+``get``::
+
+ >>> qc.get(1).name
+ u'Philosophy'
+ >>> qc.get(3) is None
+ True
+ >>> qc.get(3, 'foo')
+ 'foo'
+
+``__contains__``::
+
+ >>> 1 in qc
+ True
+ >>> 3 in qc
+ False
+
+``has_key``::
+
+ >>> qc.has_key(1)
+ True
+ >>> qc.has_key(3)
+ False
+
+``len``::
+
+ >>> len(qc)
+ 2
Modified: megrok.rdb/trunk/src/megrok/rdb/__init__.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/__init__.py 2008-08-20 17:13:59 UTC (rev 90034)
+++ megrok.rdb/trunk/src/megrok/rdb/__init__.py 2008-08-20 17:42:48 UTC (rev 90035)
@@ -1,4 +1,4 @@
-from megrok.rdb.components import Model, Container
+from megrok.rdb.components import Model, Container, QueryContainer
from megrok.rdb.schema import Fields
from megrok.rdb.directive import key, metadata, tablename, reflected
from megrok.rdb.setup import setupDatabase
Modified: megrok.rdb/trunk/src/megrok/rdb/components.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/components.py 2008-08-20 17:13:59 UTC (rev 90034)
+++ megrok.rdb/trunk/src/megrok/rdb/components.py 2008-08-20 17:42:48 UTC (rev 90035)
@@ -1,6 +1,7 @@
from sqlalchemy.orm.collections import MappedCollection, collection
from zope.interface import implements
+from zope.location.interfaces import ILocation
from grokcore.component import Context
from grok.interfaces import IContainer
@@ -26,7 +27,7 @@
"don't know how to do keying with composite primary keys")
class Container(MappedCollection):
- implements(IContainer)
+ implements(IContainer, ILocation)
def __init__(self, *args, **kw):
rdb_key = directive.key.bind().get(self)
@@ -73,3 +74,55 @@
session.flush()
key = self.keyfunc(value)
self.__setitem__(key, value, _sa_initiator)
+
+class QueryContainer(object):
+ """A read-only Container backed by set of SQLAlchemy queries.
+
+ This container is often used as the "root" object for an application.
+ """
+ # XXX should really only implement IReadContainer, but this requires
+ # a bit of refactoring in Grok
+ implements(IContainer, ILocation)
+
+ def query(self):
+ raise NotImplementedError
+
+ def __getitem__(self, key):
+ result = self.query().get(key)
+ if result is None:
+ raise KeyError(key)
+ result.__parent__ = self
+ result.__name__ = key
+ return result
+
+ def get(self, key, default=None):
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def __contains__(self, key):
+ try:
+ self[key]
+ return True
+ except KeyError:
+ return False
+
+ def has_key(self, key):
+ return key in self
+
+ def keys(self):
+ raise NotImplementedError
+
+ def __iter__(self):
+ raise NotImplementedError
+
+ def values(self):
+ raise NotImplementedError
+
+ def items(self):
+ raise NotImplementedError
+
+ def __len__(self):
+ return self.query().count()
+
More information about the Checkins
mailing list