Commit 86d9b10d authored by Matthew Somerville's avatar Matthew Somerville
Browse files

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).
parent 2926559c
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -8,12 +8,9 @@ from django.db.models import Field, IntegerField, Transform
from django.utils import six
from django.utils.translation import string_concat, ugettext_lazy as _

__all__ = ['ArrayField']

from .utils import AttributeSetter

class AttributeSetter(object):
    def __init__(self, name, value):
        setattr(self, name, value)
__all__ = ['ArrayField']


class ArrayField(Field):
+18 −7
Original line number Diff line number Diff line
@@ -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)
+3 −0
Original line number Diff line number Diff line
class AttributeSetter(object):
    def __init__(self, name, value):
        setattr(self, name, value)
+1 −1
Original line number Diff line number Diff line
@@ -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\\": \\"[)\\"}", '