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.translation import string_concat, ugettext_lazy as _
from .utils import AttributeSetter
__all__ = ['ArrayField']
class AttributeSetter(object):
def __init__(self, name, value):
setattr(self, name, value)
class ArrayField(Field):
empty_strings_allowed = False
default_error_messages = {

View File

@ -3,10 +3,11 @@ import json
from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange, Range
from django.contrib.postgres import forms, lookups
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.utils import six
from .utils import AttributeSetter
__all__ = [
'RangeField', 'IntegerRangeField', 'BigIntegerRangeField',
'FloatRangeField', 'DateTimeRangeField', 'DateRangeField',
@ -27,22 +28,32 @@ class RangeField(models.Field):
def to_python(self, value):
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)):
value = self.range_type(value[0], value[1])
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):
value = self._get_val_from_obj(obj)
if value is None:
return None
if value.isempty:
return json.dumps({"empty": True})
return json.dumps({
"lower": value.lower,
"upper": value.upper,
"bounds": value._bounds,
}, cls=DjangoJSONEncoder)
base_field = self.base_field
result = {"bounds": value._bounds}
for end in ('lower', 'upper'):
obj = AttributeSetter(base_field.attname, getattr(value, end))
result[end] = base_field.value_to_string(obj)
return json.dumps(result)
def formfield(self, **kwargs):
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
class TestSerialization(TestCase):
test_data = (
'[{"fields": {"ints": "{\\"upper\\": 10, \\"lower\\": 0, '
'[{"fields": {"ints": "{\\"upper\\": \\"10\\", \\"lower\\": \\"0\\", '
'\\"bounds\\": \\"[)\\"}", "floats": "{\\"empty\\": true}", '
'"bigints": null, "timestamps": "{\\"upper\\": \\"2014-02-02T12:12:12\\", '
'\\"lower\\": \\"2014-01-01T00:00:00\\", \\"bounds\\": \\"[)\\"}", '