from google.appengine.ext import db
from google.appengine.ext.db import polymodel
_connection_model_superclass = polymodel.PolyModel
class ConnectionModelMetaclass(type(_connection_model_superclass)):
def __new__(cls, name, bases, dct):
myname = name.replace('ConnectionModel','').lower()
if myname:
#this is not the baseclass
to_collection_name = 'myto_%s_connections' % myname #or any other naming scheme you like
from_collection_name = 'myfrom_%s_connections' % myname #or any other naming scheme you like
myto = 'myto_%s'%myname
myfrom = 'myfrom_%s'%myname
dct[myto] = db.ReferenceProperty(collection_name = to_collection_name)
dct[myfrom] = db.ReferenceProperty(collection_name = from_collection_name)
if 'put' in dct:
myput = dct['put']
else:
myput = None
def put(self):
setattr(self, myto, self.myto)
setattr(self, myfrom, self.myfrom)
self._validate_connected_types()
if myput is not None:
myput(self)
else:
MyClass = eval(name)
super(MyClass, self).put()
dct['put'] = put
return super(ConnectionModelMetaclass, cls).__new__(cls, name, bases, dct)
class ConnectionModel(_connection_model_superclass):
__metaclass__ = ConnectionModelMetaclass
ALLOWED_CONNECTIONS = {}#empty dict means anything goes. dict if of kind tuple->tuple
timestamp = db.DateTimeProperty(auto_now = True)
myto = db.ReferenceProperty(collection_name = 'myto_connections')
myfrom = db.ReferenceProperty(collection_name = 'myfrom_connections')
connection_index = db.StringProperty()#for strict sorting and paging of connections
def _validate_connected_types(self):
if None in (self.myfrom, self.myto):
raise AttributeError
if not self._check_connection():
raise AttributeError(\
'Connection %s --> %s is not allowed for class %s',
self.myfrom.__class__.__name__,
self.myto.__class__.__name__,
self.__class__)
def _check_connection(self):
if len(self.ALLOWED_CONNECTIONS) == 0:
return True
for froms, tos in self.ALLOWED_CONNECTIONS.iteritems():
if isinstance(self.myfrom, froms):
if isinstance(self.myto, tos):
return True
return False
def put(self):
if not self.connection_index:
self.connection_index = '%s|%s|%s' % \
(self.timestamp, self.myfrom.key().name(),\
self.myto.key().name())
super(ConnectionModel, self).put()
class LikeConnectionModel(ConnectionModel):
ALLOWED_CONNECTIONS = {UserModel : ImageModel}
class FollowConnectionModel(ConnectionModel):
ALLOWED_CONNECTIONS = {UserModel : (UserModel, ImageModel) }#users can follow users and (what the heck) follow images
Diff to Previous Revision
--- revision 2 2012-07-29 12:58:20
+++ revision 3 2012-07-29 13:01:39
@@ -34,8 +34,6 @@
__metaclass__ = ConnectionModelMetaclass
ALLOWED_CONNECTIONS = {}#empty dict means anything goes. dict if of kind tuple->tuple
timestamp = db.DateTimeProperty(auto_now = True)
- myto_kind = aetycoon.DerivedProperty(lambda self: self.myto.kind())
- myfrom_kind = aetycoon.DerivedProperty(lambda self: self.myfrom.kind())
myto = db.ReferenceProperty(collection_name = 'myto_connections')
myfrom = db.ReferenceProperty(collection_name = 'myfrom_connections')
connection_index = db.StringProperty()#for strict sorting and paging of connections