modified model metaclass to replace column definitions with properties that modify the columns value member instead of removing them until instantiation
This commit is contained in:
@@ -21,6 +21,8 @@ class BaseColumn(object):
|
|||||||
self.default = default
|
self.default = default
|
||||||
self.null = null
|
self.null = null
|
||||||
|
|
||||||
|
self.value = None
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
"""
|
"""
|
||||||
Returns a cleaned and validated value. Raises a ValidationError
|
Returns a cleaned and validated value. Raises a ValidationError
|
||||||
@@ -40,6 +42,14 @@ class BaseColumn(object):
|
|||||||
"""
|
"""
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def to_database(self, value):
|
||||||
|
"""
|
||||||
|
Converts python value into database value
|
||||||
|
"""
|
||||||
|
if value is None and self.has_default:
|
||||||
|
return self.get_default()
|
||||||
|
return value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_default(self):
|
def has_default(self):
|
||||||
return bool(self.default)
|
return bool(self.default)
|
||||||
@@ -48,6 +58,33 @@ class BaseColumn(object):
|
|||||||
def is_primary_key(self):
|
def is_primary_key(self):
|
||||||
return self.primary_key
|
return self.primary_key
|
||||||
|
|
||||||
|
#methods for replacing column definitions with properties that interact
|
||||||
|
#with a column's value member
|
||||||
|
#this will allow putting logic behind value access (lazy loading, etc)
|
||||||
|
def _getval(self):
|
||||||
|
""" This columns value getter """
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
def _setval(self, val):
|
||||||
|
""" This columns value setter """
|
||||||
|
self.value = val
|
||||||
|
|
||||||
|
def _delval(self):
|
||||||
|
""" This columns value deleter """
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_property(self, allow_delete=True):
|
||||||
|
"""
|
||||||
|
Returns the property object that will set and get this
|
||||||
|
column's value and be assigned to this column's model attribute
|
||||||
|
"""
|
||||||
|
getval = lambda slf: self._getval()
|
||||||
|
setval = lambda slf, val: self._setval(val)
|
||||||
|
delval = lambda slf: self._delval()
|
||||||
|
if not allow_delete:
|
||||||
|
return property(getval, setval)
|
||||||
|
return property(getval, setval, delval)
|
||||||
|
|
||||||
def get_default(self):
|
def get_default(self):
|
||||||
if self.has_default:
|
if self.has_default:
|
||||||
if callable(self.default):
|
if callable(self.default):
|
||||||
@@ -55,14 +92,6 @@ class BaseColumn(object):
|
|||||||
else:
|
else:
|
||||||
return self.default
|
return self.default
|
||||||
|
|
||||||
def to_database(self, value):
|
|
||||||
"""
|
|
||||||
Converts python value into database value
|
|
||||||
"""
|
|
||||||
if value is None and self.has_default:
|
|
||||||
return self.get_default()
|
|
||||||
return value
|
|
||||||
|
|
||||||
def get_column_def(self):
|
def get_column_def(self):
|
||||||
"""
|
"""
|
||||||
Returns a column definition for CQL table definition
|
Returns a column definition for CQL table definition
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class BaseModel(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def pk(self):
|
def pk(self):
|
||||||
""" Returns the object's primary key, regardless of it's name """
|
""" Returns the object's primary key """
|
||||||
return getattr(self, self._pk_name)
|
return getattr(self, self._pk_name)
|
||||||
|
|
||||||
#dynamic column methods
|
#dynamic column methods
|
||||||
@@ -78,26 +78,31 @@ class ModelMetaClass(type):
|
|||||||
#and set default column names
|
#and set default column names
|
||||||
_columns = {}
|
_columns = {}
|
||||||
pk_name = None
|
pk_name = None
|
||||||
|
|
||||||
|
def _transform_column(col_name, col_obj):
|
||||||
|
_columns[col_name] = col_obj
|
||||||
|
col_obj.set_db_name(col_name)
|
||||||
|
allow_delete = not col_obj.primary_key
|
||||||
|
attrs[col_name] = col_obj.get_property(allow_delete=allow_delete)
|
||||||
|
|
||||||
|
#transform column definitions
|
||||||
for k,v in attrs.items():
|
for k,v in attrs.items():
|
||||||
if isinstance(v, columns.BaseColumn):
|
if isinstance(v, columns.BaseColumn):
|
||||||
if v.is_primary_key:
|
if v.is_primary_key:
|
||||||
if pk_name:
|
if pk_name:
|
||||||
raise ModelException("More than one primary key defined for {}".format(name))
|
raise ModelException("More than one primary key defined for {}".format(name))
|
||||||
pk_name = k
|
pk_name = k
|
||||||
_columns[k] = attrs.pop(k)
|
_transform_column(k,v)
|
||||||
_columns[k].set_db_name(k)
|
|
||||||
|
|
||||||
#set primary key if it's not already defined
|
#set primary key if it's not already defined
|
||||||
if not pk_name:
|
if not pk_name:
|
||||||
_columns['id'] = columns.UUID(primary_key=True)
|
k,v = 'id', columns.UUID(primary_key=True)
|
||||||
_columns['id'].set_db_name('id')
|
_transform_column(k,v)
|
||||||
pk_name = 'id'
|
pk_name = k
|
||||||
|
|
||||||
#setup pk shortcut
|
#setup primary key shortcut
|
||||||
if pk_name != 'pk':
|
if pk_name != 'pk':
|
||||||
pk_get = lambda self: getattr(self, pk_name)
|
attrs['pk'] = _columns[pk_name].get_property(allow_delete=False)
|
||||||
pk_set = lambda self, val: setattr(self, pk_name, val)
|
|
||||||
attrs['pk'] = property(pk_get, pk_set)
|
|
||||||
|
|
||||||
#check for duplicate column names
|
#check for duplicate column names
|
||||||
col_names = set()
|
col_names = set()
|
||||||
@@ -107,7 +112,7 @@ class ModelMetaClass(type):
|
|||||||
col_names.add(v.db_field)
|
col_names.add(v.db_field)
|
||||||
|
|
||||||
#get column family name
|
#get column family name
|
||||||
cf_name = attrs.pop('db_name', None) or name
|
cf_name = attrs.pop('db_name', name)
|
||||||
|
|
||||||
#create db_name -> model name map for loading
|
#create db_name -> model name map for loading
|
||||||
db_map = {}
|
db_map = {}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
text = columns.Text()
|
text = columns.Text()
|
||||||
|
|
||||||
self.assertHasAttr(TestModel, '_columns')
|
self.assertHasAttr(TestModel, '_columns')
|
||||||
self.assertNotHasAttr(TestModel, 'id')
|
self.assertHasAttr(TestModel, 'id')
|
||||||
self.assertNotHasAttr(TestModel, 'text')
|
self.assertHasAttr(TestModel, 'text')
|
||||||
|
|
||||||
inst = TestModel()
|
inst = TestModel()
|
||||||
self.assertHasAttr(inst, 'id')
|
self.assertHasAttr(inst, 'id')
|
||||||
|
|||||||
Reference in New Issue
Block a user