Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do different Django Models with JSONFields have the same values?

I've got a model with a JSONField (a Postgres only field):

models.py:

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

class Mod(models.Model):
    data = JSONField(default={ 'name':'Model' })

So I create 2 models – ./manage.py shell:

>>> from m3d.models import Mod
>>> m1 = Mod()
>>> m1.save()
>>> m2 = Mod()
>>> m2.data['name'] = 'Model 2'
>>> m2.save()

But they have the same data['name'] values:

>>> m1.data['name']
'Model 2'
>>> m2.data['name']
'Model 2'

Note that the values are different in the database:

>>> m1a = Mod.objects.get(pk=m1.pk) # get m1 data from db
>>> m1a.data['name']
'Model'
>>> m2.data['name']
'Model 2'

but the variable m1 still has the value Model 2.

Am I missing something? Is this some sort behavior I'll need to work around?

FYI: Using Django 2.0.1

like image 726
Jeremy S. Avatar asked Dec 06 '22 12:12

Jeremy S.


1 Answers

This is covered in the documentation. The way you are setting the default for your field is incorrect:

If you give the field a default, ensure it’s a callable such as dict (for an empty default) or a callable that returns a dict (such as a function). Incorrectly using default={} creates a mutable default that is shared between all instances of JSONField.

This is the behaviour that you are seeing, where the same object is shared between the instances that you have created, and modifying one results in the other also being changed.

You need to use a callable instead, e.g., :

def get_default_data():
    return { 'name':'Model' }

class Mod(models.Model):
    data = JSONField(default=get_default_data)
like image 79
solarissmoke Avatar answered May 16 '23 06:05

solarissmoke