summaryrefslogtreecommitdiff
path: root/django/contrib/postgres/fields/jsonb.py
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2016-08-11 21:05:52 +0200
committerClaude Paroz <claude@2xlibre.net>2016-08-25 21:42:42 +0200
commit13c3e5d5a05e9c358d212d154addd703cac3bc66 (patch)
treeb718eb13592843cc6bfd1e6a56fabf23108bd191 /django/contrib/postgres/fields/jsonb.py
parent989f6108d349e0eebdc5ad26b5cb4e882cb32e47 (diff)
downloaddjango-13c3e5d5a05e9c358d212d154addd703cac3bc66.tar.gz
Fixed #25995 -- Added an encoder option to JSONField
Thanks Berker Peksag and Tim Graham for the reviews.
Diffstat (limited to 'django/contrib/postgres/fields/jsonb.py')
-rw-r--r--django/contrib/postgres/fields/jsonb.py30
1 files changed, 28 insertions, 2 deletions
diff --git a/django/contrib/postgres/fields/jsonb.py b/django/contrib/postgres/fields/jsonb.py
index ae83d9e379..e333f30619 100644
--- a/django/contrib/postgres/fields/jsonb.py
+++ b/django/contrib/postgres/fields/jsonb.py
@@ -10,6 +10,19 @@ from django.utils.translation import ugettext_lazy as _
__all__ = ['JSONField']
+class JsonAdapter(Json):
+ """
+ Customized psycopg2.extras.Json to allow for a custom encoder.
+ """
+ def __init__(self, adapted, dumps=None, encoder=None):
+ self.encoder = encoder
+ super(JsonAdapter, self).__init__(adapted, dumps=dumps)
+
+ def dumps(self, obj):
+ options = {'cls': self.encoder} if self.encoder else {}
+ return json.dumps(obj, **options)
+
+
class JSONField(Field):
empty_strings_allowed = False
description = _('A JSON object')
@@ -17,9 +30,21 @@ class JSONField(Field):
'invalid': _("Value must be valid JSON."),
}
+ def __init__(self, verbose_name=None, name=None, encoder=None, **kwargs):
+ if encoder and not callable(encoder):
+ raise ValueError("The encoder parameter must be a callable object.")
+ self.encoder = encoder
+ super(JSONField, self).__init__(verbose_name, name, **kwargs)
+
def db_type(self, connection):
return 'jsonb'
+ def deconstruct(self):
+ name, path, args, kwargs = super(JSONField, self).deconstruct()
+ if self.encoder is not None:
+ kwargs['encoder'] = self.encoder
+ return name, path, args, kwargs
+
def get_transform(self, name):
transform = super(JSONField, self).get_transform(name)
if transform:
@@ -28,13 +53,14 @@ class JSONField(Field):
def get_prep_value(self, value):
if value is not None:
- return Json(value)
+ return JsonAdapter(value, encoder=self.encoder)
return value
def validate(self, value, model_instance):
super(JSONField, self).validate(value, model_instance)
+ options = {'cls': self.encoder} if self.encoder else {}
try:
- json.dumps(value)
+ json.dumps(value, **options)
except TypeError:
raise exceptions.ValidationError(
self.error_messages['invalid'],