123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- # -*- coding: utf-8 -*-
- """
- JSONField automatically serializes most Python terms to JSON data.
- Creates a TEXT field with a default value of "{}". See test_json.py for
- more information.
- from django.db import models
- from django_extensions.db.fields import json
- class LOL(models.Model):
- extra = json.JSONField()
- """
- from __future__ import absolute_import
- import json
- import six
- import django
- from django.core.serializers.json import DjangoJSONEncoder
- from django.db import models
- def dumps(value):
- return DjangoJSONEncoder().encode(value)
- def loads(txt):
- return json.loads(txt)
- class JSONDict(dict):
- """
- Hack so repr() called by dumpdata will output JSON instead of
- Python formatted data. This way fixtures will work!
- """
- def __repr__(self):
- return dumps(self)
- class JSONList(list):
- """
- Hack so repr() called by dumpdata will output JSON instead of
- Python formatted data. This way fixtures will work!
- """
- def __repr__(self):
- return dumps(self)
- class JSONField(models.TextField):
- """
- JSONField is a generic textfield that neatly serializes/unserializes
- JSON objects seamlessly. Main thingy must be a dict object.
- """
- def __init__(self, *args, **kwargs):
- kwargs['default'] = kwargs.get('default', dict)
- models.TextField.__init__(self, *args, **kwargs)
- def get_default(self):
- if self.has_default():
- default = self.default
- if callable(default):
- default = default()
- return self.to_python(default)
- return super().get_default()
- def to_python(self, value):
- """Convert our string value to JSON after we load it from the DB"""
- if value is None or value == '':
- return {}
- if isinstance(value, six.string_types):
- res = loads(value)
- else:
- res = value
- if isinstance(res, dict):
- return JSONDict(**res)
- elif isinstance(res, list):
- return JSONList(res)
- return res
- def get_prep_value(self, value):
- if not isinstance(value, six.string_types):
- return dumps(value)
- return super(models.TextField, self).get_prep_value(value)
- if django.VERSION < (2, ):
- def from_db_value(self, value, expression, connection, context):
- return self.to_python(value)
- else:
- def from_db_value(self, value, expression, connection): # type: ignore
- return self.to_python(value)
- def get_db_prep_save(self, value, connection, **kwargs):
- """Convert our JSON object to a string before we save"""
- if value is None and self.null:
- return None
- # default values come in as strings; only non-strings should be
- # run through `dumps`
- if not isinstance(value, six.string_types):
- value = dumps(value)
- return value
- def deconstruct(self):
- name, path, args, kwargs = super().deconstruct()
- if self.default == '{}':
- del kwargs['default']
- return name, path, args, kwargs
|