8

Environment:

  • Django 1.10.6
  • psycopg2 2.7.1
  • PostgreSQL 9.6.2 installed via Homebrew on macOS Sierra
  • Python 3.6.0 installed via Homebrew

Example model:

from django.db import models
from django.contrib.postgres.fields import JSONField


class Foo(models.Model):
    data = JSONField()

When I try to create an object, everything works as expected:

from myapp.models import Foo
x = Foo()
x.data = {'key1': 'value1'}
x.save()

And querying works as expected:

Foo.objects.filter(data__key1='value1').count()
# 1

However, when I try to retrieve that data from the object, the value of the .data attribute is a string:

from myapp.models import Foo
x = Foo.objects.get(id=1)
x.data
# '{"key1": "value1"}'
type(x.data)
# str

I would expect to get back a dict here. The problem gets recursively worse when trying to save back the object

x.save()
x = Foo.objects.get(id=1)
x.data
# '"{\\"key1\\": \\"value1\\"}"'
x.save()
x = Foo.objects.get(id=1)
x.data
# '"\\"{\\\\\\"key1\\\\\\": \\\\\\"value1\\\\\\"}\\""'
mikestef9
  • 201
  • 2
  • 7
  • That shouldn't happen. Can you show your full model? Do you have any validators, or a custom save method, or any signals attached to the save event? – Daniel Roseman Mar 13 '17 at 19:02
  • 4
    I started working backwards from other installed apps I had in my project and found the culprit to be this application https://github.com/jjkester/django-auditlog. When I removed it from MIDDLEWARE and INSTALLED_APPS, everything works as expected. Looking further, that project requres django-jsonfield and there must be some incompatibility between the two – mikestef9 Mar 13 '17 at 19:28
  • In fact it's already an open issue in that project https://github.com/jjkester/django-auditlog/issues/71 – mikestef9 Mar 13 '17 at 19:44

2 Answers2

11

Turns out you cannot use django-jsonfield and Django's native JSONField in the same project or will you run into the weird behavior as described in the question

https://bitbucket.org/schinckel/django-jsonfield/issues/57/cannot-use-in-the-same-project-as-djangos

mikestef9
  • 201
  • 2
  • 7
2

For me the problem was that the database was created from a backup and the column type was set to text when it should have been either json or jsonb.

Cleaning any invalid json then altering the column type with the following:

ALTER TABLE t ALTER COLUMN j TYPE jsonb USING j::text::jsonb;

(thanks to https://stackoverflow.com/a/28076909/2362877)

frmdstryr
  • 20,142
  • 3
  • 38
  • 32