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)
|
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={})".
#