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)
- /trunk/djblets/djblets/util/fields.py: 3 changes [ 1 2 3 ]
| /trunk/djblets/djblets/util/fields.py | |||
|---|---|---|---|
| Revision 11773 | New Change | ||
| ... | 23 lines hidden [Expand] | ||
| 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 | """ |
| ... | 77 lines hidden [Expand] | ||
| 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) |
||
- /trunk/djblets/djblets/util/fields.py: 3 changes [ 1 2 3 ]
Other reviews