Не успел, я починить PickleField
для Django, мне понадобилось создать JSONField
. Задача оказалась решенной на раз/два, плюс ко всему добавился маленький и полезный виджет для JSONField
'а, который показывает красиво отформатированный JSON в textarea
. Сразу скажу, что contribute_to_class
метод чуть менне, чем полностью, скопипастен с снипетта 377.
from django.conf import settings from django.forms.widgets import Textarea from django.db.models import SubfieldBase, TextField from django.utils import simplejson class JSONField(TextField): __metaclass__ = SubfieldBase def contribute_to_class(self, cls, name): super(JSONField, self).contribute_to_class(cls, name) def get_json(model): return self.get_db_prep_value(getattr(model, self.attname)) setattr(cls, 'get_%s_json' % self.name, get_json) def set_json(model, json): setattr(model, self.attname, self.to_python(json)) setattr(cls, 'set_%s_json' % self.name, set_json) def formfield(self, **kwargs): kwargs['widget'] = JSONWidget(attrs={'class': 'vLargeTextField'}) return super(JSONField, self).formfield(**kwargs) def get_db_prep_value(self, value): return simplejson.dumps(value) def to_python(self, value): if not isinstance(value, basestring): return value try: return simplejson.loads(value, encoding=settings.DEFAULT_CHARSET) except ValueError, e: # If string could not parse as JSON it's means that it's Python # string saved to JSONField. return value class JSONWidget(Textarea): """ Prettify dumps of all non-string JSON data. """ def render(self, name, value, attrs=None): if not isinstance(value, basestring) and value is not None: value = simplejson.dumps(value, indent=4, sort_keys=True) return super(JSONWidget, self).render(name, value, attrs)
Ну и пару примеров использования, напоследок:
>>> # Пусть у нас есть простая модель >>> class Sample(models.Model): ... name = models.CharField(max_length=16) ... data = JSONField() >>> # Создадим модель и сохраним в data поле настройки для ShadowBox >>> sb = Sample.objects.create(name='ShadowBox', ... data={'autoDimensions': True, ... 'overlayOpacity': 0.5, ... 'skipSetup': True}) >>> # Теперь мы хотим напечатать эти настройки где-то в шаблоне >>> sb.get_data_json() '{"overlayOpacity": 0.5, "autoDimensions": true, "skipSetup": true}' >>> # Вспомним, что нам вообщем-то не зачем кастомное значение для overlayOpacity >>> del sb.data['overlayOpacity'] >>> sb.save() >>> # И опять напечатаем настройки в шаблоне >>> sb.get_data_json() '{"autoDimensions": true, "skipSetup": true}'
зы. ShadowBox - это лучший лайтбокс для любого JavaScript фреймворка, имо.