Commits

Matthew Schinckel committed f0793ee

initial import

  • Participants

Comments (0)

Files changed (6)

+.bookmarks
+recursive-include jsonfield *
+django-jsonfield
+===================
+
+I had a serious need for a JSON field for django. There were a couple out
+there, but none packaged up nicely on bitbucket/github that were usable
+with ``pip install -e``.
+
+So I took the code from `David Cramer's blog`_, and packaged it up.
+
+To use, just install the package, and then use the field::
+
+
+    from django.db import models
+    import jsonfield
+    
+    class MyModel(models.Model):
+        the_json = jsonfield.JSONField()
+    
+Now, it will validate the JSON on entry, and store it as a string in the
+database.  When you instantiate/fetch the object, it will be turned back
+into a python list/dict/string.
+
+
+Todo
+----------
+
+Convert date/time objects nicely to/from ISO strings (YYYY-mm-dd HH:MM:SS 
+TZNAME). This is actually a bit tricky, as we don't know if we are expecting
+a date/time object. We may parse objects as we go, but there could be
+some performance issues with this.
+
+.. _David Cramer's blog: http://www.davidcramer.net/code/448/cleaning-up-with-json-and-sql.html

File jsonfield/__init__.py

+from fields import JSONField

File jsonfield/fields.py

+from django.db import models
+from django import forms
+from django.utils import simplejson as json
+ 
+class JSONWidget(forms.Textarea):
+    def render(self, name, value, attrs=None):
+        if not isinstance(value, basestring):
+            value = json.dumps(value, indent=2)
+        return super(JSONWidget, self).render(name, value, attrs)
+
+class JSONListWidget(forms.SelectMultiple):
+    pass
+
+class JSONFormField(forms.CharField):
+    def __init__(self, *args, **kwargs):
+        kwargs['widget'] = JSONWidget
+        super(JSONFormField, self).__init__(*args, **kwargs)
+
+    def clean(self, value):
+        """
+        The default is to have a TextField, and we will decode the string
+        that comes back from this. However, another use of this field is
+        to store a list of values, and use these in a MultipleSelect
+        widget. So, if we have an object that isn't a string, then for now
+        we will assume that is where it has come from.
+        """
+        if not value or value == "null": 
+            return
+        if isinstance(value, (str, unicode)):
+            try:
+                return json.loads(value)
+            except Exception, exc:
+                raise forms.ValidationError(u'JSON decode error: %s' % (unicode(exc),))
+        else:
+            return value
+
+
+class JSONField(models.TextField):
+    __metaclass__ = models.SubfieldBase
+
+    def formfield(self, **kwargs):
+        return super(JSONField, self).formfield(form_class=JSONFormField, **kwargs)
+
+    def to_python(self, value):
+        if isinstance(value, basestring):
+            value = json.loads(value)
+        return value
+
+    def get_db_prep_save(self, value):
+        if value is None: return
+        return json.dumps(value)
+
+    def value_to_string(self, obj):
+        value = self._get_val_from_obj(obj)
+        return self.get_db_prep_value(value)
+
+
+try:
+    from south.modelsinspector import add_introspection_rules
+    add_introspection_rules([], ['^jsonfield\.fields\.JSONField'])
+except ImportError:
+    pass
+from distutils.core import setup
+
+setup(
+    name = "jsonfield",
+    version = "0.6",
+    description = "JSONField for django models",
+    url = "http://bitbucket.org/schinckel/django-jsonfield/",
+    author = "Matthew Schinckel",
+    author_email = "matt@schinckel.net",
+    packages = [
+        "jsonfield",
+    ],
+    classifiers = [
+        'Programming Language :: Python',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Framework :: Django',
+    ],
+)