This is a custom field that lets you easily store JSON data in one of your model fields. This is updated to work with Django 1.1.
Example: (models.py)
from django.db import models
import JSONField
class MyModel(models.Model):
info = JSONField()
Example: (shell)
>>> obj = MyModel.objects.all()[0]
>>> type(obj.info)
<type 'NoneType'>
>>> obj.info = {"test": [1, 2, 3]}
>>> obj.save()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | from django.db import models
from django.core.serializers.json import DjangoJSONEncoder
from django.utils import simplejson as json
class JSONField(models.TextField):
"""JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly"""
# Used so to_python() is called
__metaclass__ = models.SubfieldBase
def to_python(self, value):
"""Convert our string value to JSON after we load it from the DB"""
if value == "":
return None
try:
if isinstance(value, basestring):
return json.loads(value)
except ValueError:
pass
return value
def get_db_prep_save(self, value):
"""Convert our JSON object to a string before we save"""
if value == "":
return None
if isinstance(value, dict):
value = json.dumps(value, cls=DjangoJSONEncoder)
return super(JSONField, self).get_db_prep_save(value)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
I have problems loading json (with loaddata) that has been dumped (with dumpdata) from a PostgreSQL database. The to_python method is given a value like:
and this leads to the error message:
loads() seems to expect something like
Inserting something like
before line 19 cures the problem, but that doesn't look like an elegant solution, isn't it?
#
This worked a little better for me. Though I am still not all that happy with it.
#
Last sentence should actually read
If a string is the sole value at the point the field is instanced, to_python attempts to decode the sting because it is derived from basestring but cannot be decoded
#
jb0t: I updated what you added, thanks.
cpesch: I'm really not sure, I don't have PostgreSQL installed on my machine. Also no, that doesn't look like a very elegant solution. If you can come up with something let me know and I'll add it.
#
a hopefully elegant solution :)
value = dict(map(lambda n: map(str, n), value.items()))
#
fmardini: I think that may cover most use cases, but simply mapping complex objects to str isn't going to work for everyone.
#
I was being thrown for a loop with e.g. "Error binding parameter" (using sqlite) when trying to save a model object that had a JSONField. Turns out I was passing in a list, not a dict (valid JSON), and this JSONField doesn't handle lists. The quick fix has line 32 become:
#
I'm only using JSONField for holding dictionaries, which I suspect is pretty common. So, I took out the other options. Use like "properties = DictField(default={})".
#
modified it, so it can hold lists and does serialize (at least i tried json serialization) also modified after the docs to use get_prep_value, since they write its the function to use as antidote to to_python.
class JSONField(models.TextField): """JSONField is a generic textfield that neatly serializes/unserializes JSON objects seamlessly"""
#
Fix for 1.4. Need to add connection into the get_db_prep_save()
#
Please login first before commenting.