Instead of using DjangoJSONEncoder, use base_field's value_to_string.

Note this means the serialization of e.g. IntegerRangeField now has
strings for lower and upper, so use to_python when they came back in
(same behaviour as ArrayField, hopefully, from where I also got the
set_attributes_from_name function).
This commit is contained in:
Matthew Somerville 2015-06-06 12:55:04 +01:00
parent 2926559cce
commit 86d9b10dc3
4 changed files with 24 additions and 13 deletions

View File

@ -8,14 +8,11 @@ from django.db.models import Field, IntegerField, Transform
from django.utils import six from django.utils import six
from django.utils.translation import string_concat, ugettext_lazy as _ from django.utils.translation import string_concat, ugettext_lazy as _
from .utils import AttributeSetter
__all__ = ['ArrayField'] __all__ = ['ArrayField']
class AttributeSetter(object):
def __init__(self, name, value):
setattr(self, name, value)
class ArrayField(Field): class ArrayField(Field):
empty_strings_allowed = False empty_strings_allowed = False
default_error_messages = { default_error_messages = {

View File

@ -3,10 +3,11 @@ import json
from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange, Range from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange, Range
from django.contrib.postgres import forms, lookups from django.contrib.postgres import forms, lookups
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models from django.db import models
from django.utils import six from django.utils import six
from .utils import AttributeSetter
__all__ = [ __all__ = [
'RangeField', 'IntegerRangeField', 'BigIntegerRangeField', 'RangeField', 'IntegerRangeField', 'BigIntegerRangeField',
'FloatRangeField', 'DateTimeRangeField', 'DateRangeField', 'FloatRangeField', 'DateTimeRangeField', 'DateRangeField',
@ -27,22 +28,32 @@ class RangeField(models.Field):
def to_python(self, value): def to_python(self, value):
if isinstance(value, six.string_types): if isinstance(value, six.string_types):
value = self.range_type(**json.loads(value)) # Assume we're deserializing
vals = json.loads(value)
for end in ('lower', 'upper'):
if end in vals:
vals[end] = self.base_field.to_python(vals[end])
value = self.range_type(**vals)
elif isinstance(value, (list, tuple)): elif isinstance(value, (list, tuple)):
value = self.range_type(value[0], value[1]) value = self.range_type(value[0], value[1])
return value return value
def set_attributes_from_name(self, name):
super(RangeField, self).set_attributes_from_name(name)
self.base_field.set_attributes_from_name(name)
def value_to_string(self, obj): def value_to_string(self, obj):
value = self._get_val_from_obj(obj) value = self._get_val_from_obj(obj)
if value is None: if value is None:
return None return None
if value.isempty: if value.isempty:
return json.dumps({"empty": True}) return json.dumps({"empty": True})
return json.dumps({ base_field = self.base_field
"lower": value.lower, result = {"bounds": value._bounds}
"upper": value.upper, for end in ('lower', 'upper'):
"bounds": value._bounds, obj = AttributeSetter(base_field.attname, getattr(value, end))
}, cls=DjangoJSONEncoder) result[end] = base_field.value_to_string(obj)
return json.dumps(result)
def formfield(self, **kwargs): def formfield(self, **kwargs):
kwargs.setdefault('form_class', self.form_field) kwargs.setdefault('form_class', self.form_field)

View File

@ -0,0 +1,3 @@
class AttributeSetter(object):
def __init__(self, name, value):
setattr(self, name, value)

View File

@ -291,7 +291,7 @@ class TestQueringWithRanges(TestCase):
@skipUnlessPG92 @skipUnlessPG92
class TestSerialization(TestCase): class TestSerialization(TestCase):
test_data = ( test_data = (
'[{"fields": {"ints": "{\\"upper\\": 10, \\"lower\\": 0, ' '[{"fields": {"ints": "{\\"upper\\": \\"10\\", \\"lower\\": \\"0\\", '
'\\"bounds\\": \\"[)\\"}", "floats": "{\\"empty\\": true}", ' '\\"bounds\\": \\"[)\\"}", "floats": "{\\"empty\\": true}", '
'"bigints": null, "timestamps": "{\\"upper\\": \\"2014-02-02T12:12:12\\", ' '"bigints": null, "timestamps": "{\\"upper\\": \\"2014-02-02T12:12:12\\", '
'\\"lower\\": \\"2014-01-01T00:00:00\\", \\"bounds\\": \\"[)\\"}", ' '\\"lower\\": \\"2014-01-01T00:00:00\\", \\"bounds\\": \\"[)\\"}", '