Last active
October 9, 2017 05:44
-
-
Save fzlee/dfd1d8730b061903b7491b1a2077cc21 to your computer and use it in GitHub Desktop.
Django Field: StaticJSONFiled which buys you flexibility on mass data preservation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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