adding single instance delete method and supporting unit test

adding column type stubs
updating readme
This commit is contained in:
Blake Eggleston
2012-11-11 11:43:05 -08:00
parent b6042ac57a
commit 4764b492eb
6 changed files with 80 additions and 24 deletions

View File

@@ -1,16 +1,22 @@
cassandraengine
===============
Django ORM / Mongoengine style ORM for Cassandra
Python Cassandra ORM in the style of django / mongoengine
In it's current state you can define column families, create and delete column families
based on your model definiteions, save models and retrieve models by their primary keys.
That's about it. Also, there are only 2 tests and the CQL stuff is very simplistic at this point.
That's about it. Also, the CQL stuff is pretty simple at this point.
##TODO
* Complex queries (class Q(object))
* Match column names to mongoengine field names?
* mongoengine fields? URLField, EmbeddedDocument, ListField, DictField
* column ttl?
* ForeignKey/DBRef fields?
* dynamic column support
* return None when row isn't found in find()
* tests
* query functionality
* nice column and model class __repr__

View File

@@ -106,6 +106,9 @@ class Integer(BaseColumn):
class DateTime(BaseColumn):
db_type = 'timestamp'
def __init__(self, **kwargs):
super(DateTime, self).__init__(**kwargs)
raise NotImplementedError
class UUID(BaseColumn):
"""
@@ -153,4 +156,23 @@ class Float(BaseColumn):
class Decimal(BaseColumn):
db_type = 'decimal'
#TODO: this
def __init__(self, **kwargs):
super(DateTime, self).__init__(**kwargs)
raise NotImplementedError
class Counter(BaseColumn):
def __init__(self, **kwargs):
super(DateTime, self).__init__(**kwargs)
raise NotImplementedError
#TODO: research supercolumns
#http://wiki.apache.org/cassandra/DataModel
class List(BaseColumn):
def __init__(self, **kwargs):
super(DateTime, self).__init__(**kwargs)
raise NotImplementedError
class Dict(BaseColumn):
def __init__(self, **kwargs):
super(DateTime, self).__init__(**kwargs)
raise NotImplementedError

View File

@@ -21,17 +21,20 @@ class Manager(object):
#trim to less than 48 characters or cassandra will complain
cf_name = cf_name[-48:]
return cf_name
def column_family_definition(self):
def __call__(self, **kwargs):
"""
Generates a definition used for tale creation
filter shortcut
"""
return self.filter(**kwargs)
def find(self, pk):
"""
Returns the row corresponding to the primary key value given
"""
values = QuerySet(self.model).find(pk)
if values is None: return
#change the column names to model names
#in case they are different
field_dict = {}
@@ -55,6 +58,10 @@ class Manager(object):
def create(self, **kwargs):
return self.model(**kwargs).save()
def delete(self, **kwargs):
pass
#----single instance methods----
def _save_instance(self, instance):
"""
The business end of save, this is called by the models
@@ -63,18 +70,15 @@ class Manager(object):
"""
QuerySet(self.model).save(instance)
def _delete_instance(self, instance):
"""
Deletes a single instance
"""
QuerySet(self.model).delete_instance(instance)
#----column family create/delete----
def _create_column_family(self):
QuerySet(self.model)._create_column_family()
def _delete_column_family(self):
QuerySet(self.model)._delete_column_family()
def delete(self, **kwargs):
pass
def __call__(self, **kwargs):
"""
filter shortcut
"""
return self.filter(**kwargs)

View File

@@ -65,7 +65,8 @@ class BaseModel(object):
return self
def delete(self):
pass
""" Deletes this instance """
self.objects._delete_instance(self)
class ModelMetaClass(type):

View File

@@ -42,7 +42,7 @@ class QuerySet(object):
"""
cur = self._cursor
values = cur.fetchone()
if values is None: return None
if values is None: return
names = [i[0] for i in cur.description]
value_dict = dict(zip(names, values))
return value_dict
@@ -64,15 +64,12 @@ class QuerySet(object):
return QuerySet(self.model, query_args=qargs)
def exclude(self, **kwargs):
"""
Need to invert the logic for all kwargs
"""
""" Need to invert the logic for all kwargs """
pass
def count(self):
"""
Returns the number of rows matched by this query
"""
""" Returns the number of rows matched by this query """
qs = 'SELECT COUNT(*) FROM {}'.format(self.column_family_name)
def find(self, pk):
"""
@@ -128,6 +125,23 @@ class QuerySet(object):
cur = conn.cursor()
cur.execute(qs, field_values)
#----delete---
def delete(self):
"""
Deletes the contents of a query
"""
def delete_instance(self, instance):
""" Deletes one instance """
pk_name = self.model._pk_name
qs = ['DELETE FROM {}'.format(self.column_family_name)]
qs += ['WHERE {0}=:{0}'.format(pk_name)]
qs = ' '.join(qs)
conn = get_connection()
cur = conn.cursor()
cur.execute(qs, {pk_name:instance.pk})
def _create_column_family(self):
#construct query string
qs = ['CREATE TABLE {}'.format(self.column_family_name)]

View File

@@ -38,6 +38,15 @@ class TestModelIO(BaseCassEngTestCase):
tm2 = TestModel.objects.find(tm.pk)
self.assertEquals(tm.count, tm2.count)
def test_model_deleting_works_properly(self):
"""
Tests that an instance's delete method deletes the instance
"""
tm = TestModel.objects.create(count=8, text='123456789')
tm.delete()
tm2 = TestModel.objects.find(tm.pk)
self.assertIsNone(tm2)
def test_nullable_columns_are_saved_properly(self):
"""
Tests that nullable columns save without any trouble