diff options
author | Claude Paroz <claude@2xlibre.net> | 2016-08-11 21:05:52 +0200 |
---|---|---|
committer | Claude Paroz <claude@2xlibre.net> | 2016-08-25 21:42:42 +0200 |
commit | 13c3e5d5a05e9c358d212d154addd703cac3bc66 (patch) | |
tree | b718eb13592843cc6bfd1e6a56fabf23108bd191 /django/contrib/postgres/fields/jsonb.py | |
parent | 989f6108d349e0eebdc5ad26b5cb4e882cb32e47 (diff) | |
download | django-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.py | 30 |
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'], |