Review Board

beta

Added a JSONField for models

Updated 6 months ago

Christian Hammond Reviewers
trunk reviewboard
None Navi
Added a handy little field for accessing various types of data and storing data as JSON in the database. This will be used for extensions and other upcoming stuff.
Tested with my extensions branch. I can store and access data just fine.

Diff revision 1 (Latest)

  1. /trunk/djblets/djblets/util/fields.py: 3 changes [ 1 2 3 ]
/trunk/djblets/djblets/util/fields.py
Revision 11773 New Change
24
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
25
26
import base64
26
import base64
27
from datetime import datetime
27
from datetime import datetime
28
28
29
from django.conf import settings
30
from django.core.serializers.json import DjangoJSONEncoder
29
from django.db import models
31
from django.db import models
30
from django.dispatch import dispatcher
32
from django.dispatch import dispatcher
33
from django.utils import simplejson
31
from django.utils.encoding import smart_unicode
34
from django.utils.encoding import smart_unicode
32
35
33
36
34
class Base64DecodedValue(str):
37
class Base64DecodedValue(str):
35
    """
38
    """
113
116
114
        return super(ModificationTimestampField, self).pre_save(model, add)
117
        return super(ModificationTimestampField, self).pre_save(model, add)
115
118
116
    def get_internal_type(self):
119
    def get_internal_type(self):
117
        return "DateTimeField"
120
        return "DateTimeField"
121
122
123
class JSONField(models.TextField):
124
    """
125
    A field for storing JSON-encoded data. The data is accessible as standard
126
    Python data types and is transparently encoded/decoded to/from a JSON
127
    string in the database.
128
    """
129
    def __init__(self, verbose_name=None, name=None,
130
                 encoder=DjangoJSONEncoder(), **kwargs):
131
        models.TextField.__init__(self, verbose_name, name, blank=True,
132
                                  **kwargs)
133
        self.encoder = encoder
134
135
    def db_type(self):
136
        return "text"
137
138
    def contribute_to_class(self, cls, name):
139
        def get_json(model_instance):
140
            return self.dumps(getattr(model_instance, self.attname, None))
141
142
        def set_json(model_instance, json):
143
            setattr(instance, self.attname, self.loads(json))
144
145
        super(JSONField, self).contribute_to_class(cls, name)
146
147
        setattr(cls, "get_%s_json" % self.name, get_json)
148
        setattr(cls, "set_%s_json" % self.name, set_json)
149
150
        dispatcher.connect(self.post_init, signal=models.signals.post_init,
151
                           sender=cls)
152
153
    def pre_save(self, model_instance, add):
154
        return self.dumps(getattr(model_instance, self.attname, None))
155
156
    def post_init(self, instance=None):
157
        value = self.value_from_object(instance)
158
159
        if value:
160
            value = self.loads(value)
161
        else:
162
            value = {}
163
164
        setattr(instance, self.attname, value)
165
166
    def dumps(self, data):
167
        return self.encoder.encode(data)
168
169
    def loads(self, s):
170
        return simplejson.loads(s, encoding=settings.DEFAULT_CHARSET)
  1. /trunk/djblets/djblets/util/fields.py: 3 changes [ 1 2 3 ]