From 6f5ab41b8ef48194911ad43e0d9e1c70ea77f98f Mon Sep 17 00:00:00 2001 From: Seth Denner Date: Fri, 13 May 2016 17:27:35 -0700 Subject: [PATCH] FieldUUID * Django doesn't like it when you have more than one autofield on a model so I refactored FieldUUID into a seperate class. --- djangocassandra/db/fields.py | 65 +++++++++++++++++++++++++++++++++++- djangocassandra/db/meta.py | 1 + setup.py | 2 +- tests/models.py | 10 +++++- tests/test_fields.py | 38 +++++++++++++++++++++ 5 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 tests/test_fields.py diff --git a/djangocassandra/db/fields.py b/djangocassandra/db/fields.py index 4a2b3c65..4d104b0d 100644 --- a/djangocassandra/db/fields.py +++ b/djangocassandra/db/fields.py @@ -4,7 +4,8 @@ from django.db.models import ( Field, AutoField, - SubfieldBase + SubfieldBase, + CharField ) from django.utils.translation import ugettext_lazy as _ @@ -75,6 +76,68 @@ def value_to_string( ]) +class FieldUUID(with_metaclass(SubfieldBase, CharField)): + description = _('UUID') + + default_error_messages = { + 'invalid': _("'%(value)s' value must be a valid UUID."), + } + + def __init__( + self, + *args, + **kwargs + ): + if 'default' not in kwargs: + kwargs['default'] = uuid.uuid4 + + super(FieldUUID, self).__init__( + *args, + **kwargs + ) + + def to_python( + self, + value + ): + if isinstance(value, uuid.UUID): + return str(value) + + else: + return value + + def get_prep_value(self, value): + value = super(FieldUUID, self).get_prep_value(value) + if ( + value is None or + isinstance(value, uuid.UUID) + ): + return value + + return uuid.UUID(value) + + def get_internal_type(self): + return 'FieldUUID' + + @staticmethod + def get_auto_value(self): + return uuid.uuid4() + + def value_to_string(self, value): + if isinstance(value, basestring): + return value + + try: + return str(value) + + except (TypeError, ValueError): + raise Exception( + self.error_messages['invalid'], + code='invalid', + params={'value': value}, + ) + + class AutoFieldUUID(with_metaclass(SubfieldBase, AutoField)): description = _('UUID') diff --git a/djangocassandra/db/meta.py b/djangocassandra/db/meta.py index bf9d780f..2073ee2c 100644 --- a/djangocassandra/db/meta.py +++ b/djangocassandra/db/meta.py @@ -18,6 +18,7 @@ internal_type_to_column_map = { 'AutoField': columns.Integer, 'AutoFieldUUID': columns.UUID, + 'FieldUUID': columns.UUID, 'RelatedAutoField': columns.UUID, 'ForeignKey': columns.UUID, 'OneToOneField': columns.UUID, diff --git a/setup.py b/setup.py index cbd0b005..68999932 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='djangocassandra', - version='0.4.2', + version='0.4.3', description='Cassandra support for the Django web framework', long_description=( 'The Cassandra database backend for Django has been ' diff --git a/tests/models.py b/tests/models.py index aa4092e4..187bb47e 100644 --- a/tests/models.py +++ b/tests/models.py @@ -26,7 +26,10 @@ ForeignKey ) -from djangocassandra.db.fields import AutoFieldUUID +from djangocassandra.db.fields import ( + AutoFieldUUID, + FieldUUID +) from djangocassandra.db.models import ( ColumnFamilyModel, ColumnFamilyManager @@ -157,6 +160,11 @@ class RelatedModelC(Model): ) +class UUIDFieldModel(Model): + id = AutoFieldUUID(primary_key=True) + uuid = FieldUUID() + + class ClusterPrimaryKeyModel(ColumnFamilyModel): class Cassandra: clustering_keys = ['field_2', 'field_3'] diff --git a/tests/test_fields.py b/tests/test_fields.py new file mode 100644 index 00000000..5a6e96bf --- /dev/null +++ b/tests/test_fields.py @@ -0,0 +1,38 @@ +import uuid +from unittest import TestCase + +from .models import ( + UUIDFieldModel +) + +from .util import ( + connect_db, + destroy_db, + create_model +) + + +class UUIDFieldModelTestCase(TestCase): + def setUp(self): + self.connection = connect_db() + self.cached_rows = {} + + create_model( + self.connection, + UUIDFieldModel + ) + + import django + django.setup() + + def tearDown(self): + destroy_db(self.connection) + + def test_create_uuid_field_model(self): + instance = UUIDFieldModel.objects.create() + + self.assertIsNotNone(instance) + uuid.UUID(instance.uuid) + uuid.UUID(instance.id) + + UUIDFieldModel.objects.get(pk=instance.pk)