Skip to content

Commit

Permalink
Cleanup: grouped schema mode related methods in DictionaryField
Browse files Browse the repository at this point in the history
  • Loading branch information
nemesifier committed Sep 28, 2014
1 parent 40e19a5 commit fe0c480
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 34 deletions.
6 changes: 3 additions & 3 deletions django_hstore/descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

class HStoreDescriptor(models.fields.subclassing.Creator):
_DictClass = HStoreDict

def __init__(self, *args, **kwargs):
self.schema_mode = kwargs.pop('schema_mode', False)
super(HStoreDescriptor, self).__init__(*args, **kwargs)

def __set__(self, obj, value):
value = self.field.to_python(value)
if isinstance(value, dict):
Expand All @@ -25,4 +25,4 @@ def __set__(self, obj, value):


class HStoreReferenceDescriptor(HStoreDescriptor):
_DictClass = HStoreReferenceDict
_DictClass = HStoreReferenceDict
28 changes: 14 additions & 14 deletions django_hstore/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@ def contribute_to_class(self, cls, name):
if self.schema:
self._create_hstore_virtual_fields(cls, name)

def formfield(self, **kwargs):
kwargs['form_class'] = forms.DictionaryField
return super(DictionaryField, self).formfield(**kwargs)

def _value_to_python(self, value):
return value

def south_field_triple(self):
name, args, kwargs = super(DictionaryField, self).south_field_triple()
# if schema mode replace the default value {} with None as {} would break south
if self.schema_mode:
kwargs['default'] = None
return name, args, kwargs

def _validate_schema(self, schema):
if not isinstance(schema, list):
raise ValueError('schema parameter must be a list')
Expand Down Expand Up @@ -149,20 +163,6 @@ def _create_hstore_virtual_fields(self, cls, hstore_field_name):
# add this field to hstore_virtual_fields dict
cls._hstore_virtual_fields[field['name']] = virtual_field

def formfield(self, **kwargs):
kwargs['form_class'] = forms.DictionaryField
return super(DictionaryField, self).formfield(**kwargs)

def _value_to_python(self, value):
return value

def south_field_triple(self):
name, args, kwargs = super(DictionaryField, self).south_field_triple()
# if schema mode replace the default value {} with None as {} would break south
if self.schema_mode:
kwargs['default'] = None
return name, args, kwargs

def reload_schema(self, schema):
"""
Reload schema arbitrarily at run-time
Expand Down
33 changes: 16 additions & 17 deletions django_hstore/virtual.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
]



class HStoreVirtualMixin(object):
"""
must be mixed-in with django fields
Expand All @@ -29,33 +28,33 @@ def contribute_to_class(self, cls, name):
cls._meta.add_field(self)
# add also into virtual fields in order to support admin
cls._meta.virtual_fields.append(self)

def db_type(self, connection):
"""
returning None here will cause django to exclude this field
from the concrete field list (_meta.concrete_fields)
resulting in the fact that syncdb will skip this field when creating tables in PostgreSQL
"""
return None

# begin descriptor methods

def __get__(self, instance, instance_type=None):
"""
retrieve value from hstore dictionary
"""
if instance is None:
raise AttributeError('Can only be accessed via instance')

return getattr(instance, self.hstore_field_name).get(self.name, self.default)

def __set__(self, instance, value):
"""
set value on hstore dictionary
"""
hstore_dictionary = getattr(instance, self.hstore_field_name)
hstore_dictionary[self.name] = value

# end descriptor methods


Expand All @@ -78,30 +77,30 @@ def create_hstore_virtual_field(field_cls, kwargs, hstore_field_name):
BaseField = field_cls
else:
raise ValueError('field must be either a django standard field or a subclass of django.db.models.Field')

class VirtualField(HStoreVirtualMixin, BaseField):
# keep basefield info (added for django-rest-framework-hstore)
__basefield__ = BaseField

def __init__(self, *args, **kwargs):
try:
self.hstore_field_name = hstore_field_name
except KeyError:
raise ValueError('missing hstore_field_name keyword argument')
raise ValueError('missing hstore_field_name keyword argument')
super(VirtualField, self).__init__(*args, **kwargs)

def deconstruct(self, *args, **kwargs):
"""
specific for django 1.7 and greater (migration framework)
"""
name, path, args, kwargs = super(VirtualField, self).deconstruct(*args, **kwargs)
return (name, path, args, { 'default': kwargs.get('default')})

# support DateTimeField
if BaseField == models.DateTimeField and kwargs.get('default') is None:
import datetime
kwargs['default'] = datetime.datetime.utcnow()

# support Date and DateTime in django-rest-framework-hstore
if BaseField == models.DateTimeField or BaseField == models.DateField:
def value_to_string(self, obj):
Expand All @@ -111,12 +110,12 @@ def value_to_string(self, obj):
except AttributeError as e:
return val
VirtualField.value_to_string = value_to_string

field = VirtualField(**kwargs)

if field.default == models.fields.NOT_PROVIDED:
field.default = ''

return field


Expand All @@ -125,4 +124,4 @@ def value_to_string(self, obj):
from south.modelsinspector import add_ignored_fields
add_ignored_fields(["^django_hstore\.virtual\.VirtualField"])
except ImportError:
pass
pass

0 comments on commit fe0c480

Please sign in to comment.