adding single instance delete method and supporting unit test
adding column type stubs updating readme
This commit is contained in:
12
README.md
12
README.md
@@ -1,16 +1,22 @@
|
|||||||
cassandraengine
|
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
|
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.
|
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
|
##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
|
* dynamic column support
|
||||||
* return None when row isn't found in find()
|
|
||||||
* tests
|
* tests
|
||||||
* query functionality
|
* query functionality
|
||||||
* nice column and model class __repr__
|
* nice column and model class __repr__
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ class Integer(BaseColumn):
|
|||||||
|
|
||||||
class DateTime(BaseColumn):
|
class DateTime(BaseColumn):
|
||||||
db_type = 'timestamp'
|
db_type = 'timestamp'
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(DateTime, self).__init__(**kwargs)
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
class UUID(BaseColumn):
|
class UUID(BaseColumn):
|
||||||
"""
|
"""
|
||||||
@@ -153,4 +156,23 @@ class Float(BaseColumn):
|
|||||||
class Decimal(BaseColumn):
|
class Decimal(BaseColumn):
|
||||||
db_type = 'decimal'
|
db_type = 'decimal'
|
||||||
#TODO: this
|
#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
|
||||||
|
|||||||
@@ -22,16 +22,19 @@ class Manager(object):
|
|||||||
cf_name = cf_name[-48:]
|
cf_name = cf_name[-48:]
|
||||||
return cf_name
|
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):
|
def find(self, pk):
|
||||||
"""
|
"""
|
||||||
Returns the row corresponding to the primary key value given
|
Returns the row corresponding to the primary key value given
|
||||||
"""
|
"""
|
||||||
values = QuerySet(self.model).find(pk)
|
values = QuerySet(self.model).find(pk)
|
||||||
|
if values is None: return
|
||||||
|
|
||||||
#change the column names to model names
|
#change the column names to model names
|
||||||
#in case they are different
|
#in case they are different
|
||||||
field_dict = {}
|
field_dict = {}
|
||||||
@@ -55,6 +58,10 @@ class Manager(object):
|
|||||||
def create(self, **kwargs):
|
def create(self, **kwargs):
|
||||||
return self.model(**kwargs).save()
|
return self.model(**kwargs).save()
|
||||||
|
|
||||||
|
def delete(self, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
#----single instance methods----
|
||||||
def _save_instance(self, instance):
|
def _save_instance(self, instance):
|
||||||
"""
|
"""
|
||||||
The business end of save, this is called by the models
|
The business end of save, this is called by the models
|
||||||
@@ -63,18 +70,15 @@ class Manager(object):
|
|||||||
"""
|
"""
|
||||||
QuerySet(self.model).save(instance)
|
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):
|
def _create_column_family(self):
|
||||||
QuerySet(self.model)._create_column_family()
|
QuerySet(self.model)._create_column_family()
|
||||||
|
|
||||||
def _delete_column_family(self):
|
def _delete_column_family(self):
|
||||||
QuerySet(self.model)._delete_column_family()
|
QuerySet(self.model)._delete_column_family()
|
||||||
|
|
||||||
def delete(self, **kwargs):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __call__(self, **kwargs):
|
|
||||||
"""
|
|
||||||
filter shortcut
|
|
||||||
"""
|
|
||||||
return self.filter(**kwargs)
|
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ class BaseModel(object):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
pass
|
""" Deletes this instance """
|
||||||
|
self.objects._delete_instance(self)
|
||||||
|
|
||||||
|
|
||||||
class ModelMetaClass(type):
|
class ModelMetaClass(type):
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class QuerySet(object):
|
|||||||
"""
|
"""
|
||||||
cur = self._cursor
|
cur = self._cursor
|
||||||
values = cur.fetchone()
|
values = cur.fetchone()
|
||||||
if values is None: return None
|
if values is None: return
|
||||||
names = [i[0] for i in cur.description]
|
names = [i[0] for i in cur.description]
|
||||||
value_dict = dict(zip(names, values))
|
value_dict = dict(zip(names, values))
|
||||||
return value_dict
|
return value_dict
|
||||||
@@ -64,15 +64,12 @@ class QuerySet(object):
|
|||||||
return QuerySet(self.model, query_args=qargs)
|
return QuerySet(self.model, query_args=qargs)
|
||||||
|
|
||||||
def exclude(self, **kwargs):
|
def exclude(self, **kwargs):
|
||||||
"""
|
""" Need to invert the logic for all kwargs """
|
||||||
Need to invert the logic for all kwargs
|
|
||||||
"""
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def count(self):
|
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):
|
def find(self, pk):
|
||||||
"""
|
"""
|
||||||
@@ -128,6 +125,23 @@ class QuerySet(object):
|
|||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(qs, field_values)
|
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):
|
def _create_column_family(self):
|
||||||
#construct query string
|
#construct query string
|
||||||
qs = ['CREATE TABLE {}'.format(self.column_family_name)]
|
qs = ['CREATE TABLE {}'.format(self.column_family_name)]
|
||||||
|
|||||||
@@ -38,6 +38,15 @@ class TestModelIO(BaseCassEngTestCase):
|
|||||||
tm2 = TestModel.objects.find(tm.pk)
|
tm2 = TestModel.objects.find(tm.pk)
|
||||||
self.assertEquals(tm.count, tm2.count)
|
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):
|
def test_nullable_columns_are_saved_properly(self):
|
||||||
"""
|
"""
|
||||||
Tests that nullable columns save without any trouble
|
Tests that nullable columns save without any trouble
|
||||||
|
|||||||
Reference in New Issue
Block a user