Skip to content

Instantly share code, notes, and snippets.

@fzlee
Last active October 9, 2017 05:44
Show Gist options
  • Save fzlee/dfd1d8730b061903b7491b1a2077cc21 to your computer and use it in GitHub Desktop.
Save fzlee/dfd1d8730b061903b7491b1a2077cc21 to your computer and use it in GitHub Desktop.
Django Field: StaticJSONFiled which buys you flexibility on mass data preservation
#!/usr/bin/env python
# coding: utf-8
"""
static_json.py
~~~~~~~~~~
"""
import json
from jsonfield import JSONField
class InvalidAttributeException(Exception):
pass
class StaticJSON(object):
def __init__(self, default, value=None):
value = value or {}
self.__dict__["_default"] = default
self.__dict__["_value"] = value
for k, v in self._default.items():
self.__dict__["_value"].setdefault(k, v)
def __getattr__(self, name):
if name in self.__dict__.get("_default", {}):
return self.__dict__["_value"][name]
else:
raise AttributeError(name)
def __setattr__(self, name, value):
if name == "_default" or name == "_value":
setattr(self.__dict__[name], name, value)
if name not in self.__dict__["_default"]:
raise InvalidAttributeException("{} is not a valid attribute, try {} instead".format(
name, ", ".join(self.__dict__["_default"].keys())
))
self.__dict__["_value"][name] = value
@property
def internal_value(self):
return self._value
def items(self):
""" used for serializer.to_representation
"""
return self._value.items()
def __iter__(self):
""" for i in StaticJSON:
pass
"""
for item in self._value:
yield item
def __unicode__(self):
return "<StaticJSON instance: {}>".format(json.dumps(self._value))
def __repr__(self):
return "<StaticJSON instance: {}>".format(json.dumps(self._value))
class StaticJSONField(JSONField):
"""
a JSONField that accepts attributes based on pre-defined styles
"""
def __init__(self, *args, **kwargs):
super(StaticJSONField, self).__init__(*args, **kwargs)
self._default = kwargs.get("default")
def pre_init(self, value, obj):
value = super(StaticJSONField, self).pre_init(value, obj)
if isinstance(value, StaticJSON):
return value
return StaticJSON(self._default, value)
def get_db_prep_value(self, value, connection, prepared=False):
"""Convert JSON object to a string"""
if self.null and value is None:
return None
if isinstance(value, StaticJSON):
return json.dumps(value.internal_value, **self.dump_kwargs)
else:
return json.dumps(value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment