Update dict JsonField Postgresql

46 views
Skip to first unread message

Martin Peveri

unread,
Mar 27, 2017, 9:17:42 AM3/27/17
to Django users
Hi everyone, I have a model model like this:


class ItemCampaign(models.Model):

   campaign = models.ForeignKey(
       Campaign, related_name="itemscampaign", verbose_name="Item campaña"
   )
   data = JSONField(default=dict)

   def __str__(self):
       return self.campaign.name

The field data, contains this list dict, for example:

[{'number': '1160188479', 'id': 0, 'content': 'hello', 'processed': False}, {'number': '1160188479', 'id': 1, 'content': 'hello', 'processed': False}, {'number': '1160188479', 'id': 2, 'content': 'hello', 'processed': False}, {'number': '1162341721', 'id': 3, 'content': 'hello', 'processed': False}, {'number': '1162341721', 'id': 4, 'content': 'hello', 'processed': False}, {'number': '1162341721', 'id': 5, 'content': 'hello', 'processed': False}}

I wish make is update one dict of this list:

objectitem.data[0]['processed'] =True
objectitem
.save()


But not working.

Any Idea?.

Thanks!

Melvyn Sopacua

unread,
Mar 27, 2017, 9:52:37 AM3/27/17
to django...@googlegroups.com

On Monday 27 March 2017 05:56:34 Martin Peveri wrote:

 

> But not working.

>

> Any Idea?.

 

Plenty. But start by defining "not working". Not trying to be snarky, but there are a lot of moving parts here and it's anybody's guess at this point what part is causing the problem. We don't even know how you determined it's not working (get an exception, value isn't changed, save doesn't get called, form errors ... ).

 

Here's my shot in the dark:

Django's JSONEncoder only accepts dicts as outermost structure.

--

Melvyn Sopacua

Martin Peveri

unread,
Mar 27, 2017, 10:05:38 AM3/27/17
to Django users
Hi  Melvyn, With "not working", I mean that it does nothing. For example

This line

>>> objectitem.data[0]['processed'] True

It does not return any errors

This line:

>>> objectitem.save()

Neither

So when I'm going to get the record back, it returns me the same.

>>> objectitem.data[0]
>>> False

I would have to return True. I explain? My English is not very good.

You can explain a little more this: "Django's JSONEncoder only accepts dicts as outermost structure."

I am inserting a list of dicts. For example:

>>> Model.objects.create(data={[......my dicts ]}

That's wrong?

Thanks!

Melvyn Sopacua

unread,
Mar 27, 2017, 10:28:53 AM3/27/17
to django...@googlegroups.com

Hi Martin,

 

On Monday 27 March 2017 07:05:38 Martin Peveri wrote:

> Hi Melvyn, With "not working", I mean that it does nothing. For

> example

>

> This line

>

> >>> objectitem.data[0]['processed'] = True

>

> It does not return any errors

>

> This line:

> >>> objectitem.save()

>

> Neither

>

> So when I'm going to get the record back, it returns me the same.

>

> >>> objectitem.data[0]

> >>> False

>

> I would have to return True.

 

Is this really how you typed it? Because objectitem.data[0] should be a dict or list, but not a boolean.

Could you show the output of:

 

json.dumps(objectitem.data)

 

 

> I explain? My English is not very good.

>

> You can explain a little more this: "Django's JSONEncoder only accepts

> dicts as outermost structure."

 

I'm not sure it is used for assigning data to the json field. It is used to form a django.http.JSONResponse and to serialize data to JSON, so that was a guess.

 

> I am inserting a list of dicts. For example:

> >>> Model.objects.create(data={[......my dicts ]}

>

> That's wrong?

 

Not sure, but as you typed it, it's a set, not a dict (there is no 'key':), so if python thinks any of the lists are identifcal, it'll be missing.

 

 

--

Melvyn Sopacua

Martin Peveri

unread,
Mar 27, 2017, 11:50:04 AM3/27/17
to Django users
json.dumps return this (For example, the field contains 50k of records):

[{'number': '1160188479', 'id': 0, 'content': 'hello', 'processed': False}, {'number': '1160188479', 'id': 1, 'content': 'hello', 'processed': False}, {'number': '1160188479', 'id': 2,'content': 'hello', 'processed': False}, {'number': '1162341721', 'id': 3, 'content': 'hello', 'processed': False}, {'number': '1162341721', 'id': 4, 'content': 'hello', 'processed':False}, {'number': '1162341721', 'id': 5, 'content': 'hello', 'processed': False}]

Melvyn Sopacua

unread,
Mar 27, 2017, 1:29:13 PM3/27/17
to django...@googlegroups.com

Hi,

 

On Monday 27 March 2017 08:50:04 Martin Peveri wrote:

 

Totally forgot about this gotcha:

 

> > > >>> objectitem.data[0]['processed'] = True

 

That won't work.

objectitem.data is a reference to a list of dicts

changing something inside, doesn't signal the model that it's data has changed, as the reference doesn't change.

 

You need to manipulate the data as it's own structure, then assign it:

 

data = objectitem.data

data[0]['processed'] = True

objectitem.data = data

objectitem.save()

 

If the above don't work:

objecitem.save(force_update=True, update_fields=('data',))

 

 

--

Melvyn Sopacua

Martin Peveri

unread,
Mar 27, 2017, 6:03:17 PM3/27/17
to Django users
Perfect!! This code works:

data = objectitem.data

data[0]['processed'] = True

objectitem.data = data

objectitem.save()


A last query that is not related to the insertion, but to the query.

If I want to get only records processed in True as I have to do?

This does not work, I get all the records:

objectitem.filter(data__contains=[{'processed': True}])

Thanks!!!

Melvyn Sopacua

unread,
Mar 28, 2017, 5:58:51 AM3/28/17
to django...@googlegroups.com

On Monday 27 March 2017 15:03:17 Martin Peveri wrote:

> Perfect!! This code works:

>

> data = objectitem.data

>

> data[0]['processed'] = True

>

> objectitem.data = data

>

> objectitem.save()

>

> A last query that is not related to the insertion, but to the query.

>

> If I want to get only records processed in True as I have to do?

>

> This does not work, I get all the records:

>

> objectitem.filter(data__contains=[{'processed': True}])

 

Looking at your data model, you should probably make data an ArrayField of JSONFields...

This would simplify things quite a bit.

 

That said, I would try data__contains={'processed': True}, but if that doesn't work, your problem is that your outer structure is a list, not an object, making filtering a lot harder.

 

--

Melvyn Sopacua

Martin Peveri

unread,
Mar 28, 2017, 7:48:48 AM3/28/17
to Django users
It does not work :(

With ArrayField Will I be able to filter the content of the field?. For example, if i have one record and in the field data a list of dict with 50k. Can I filter it?. That is to say, to bring only in the array the records with 'processed' true.

Thanks! 
Reply all
Reply to author
Forward
0 new messages