Django JSONField inside ArrayField

I have a problem inserting to a field using ArrayField with JSONField inside.

models.py

locations = ArrayField(JSONField(null = True,blank = True), blank=True, null = True)

Insert

location_arr = [{"locations" : "loc1","amount":Decimal(100.00)},{"locations" : "loc2","amount":Decimal(200.25)}]
instance.locations = location_arr
instance.save()

When I do this, I got

column “locations” is of type jsonb[] but expression is of type text[]

LINE 1: …d” = 2517, “locations” = ARRAY[‘{“loc…

Hint: You will need to rewrite or cast the expression.

So I tried to dump it using:

import json
location_arr = [{"locations" : "loc1","amount":Decimal(100.00)},{"locations" : "loc2","amount":Decimal(200.25)}]
instance.locations = json.dumps(location_arr)
instance.save()

then I got this

LINE 1: …d” = 2517, “locations” = ‘[{“loc”:…

DETAIL: “[” must introduce explicitly-specified array dimensions.

I am using:

  1. Django 1.9
  2. Python 2.7
  3. Postgres 9.4.10
  4. psycopg2 2.6.2

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Arrays

First of all, let’s take a close look at this important text from the Postgresql Arrays document.

Tip: Arrays are not sets; searching for specific array elements can be
a sign of database misdesign. Consider using a separate table with a
row for each item that would be an array element. This will be easier
to search, and is likely to scale better for a large number of
elements.

Most of the time, you should not be using arrays.

JSONB

JSONB is available in Django as the JSONField type. This field is more scalable and flexible than array fields and can be searched more efficiently. However if you find yourself searching inside JSONB fields all the time the above statement about Arrays is equally valid for JSONB.

Now what do you have in your system? A an array that holds JSONB field. This is a disaster waiting to happen. Please normalize your data.

Recap

so when to use ArrayField?

On the rare occasion when you don’t need to search in that column and you don’t need to use that column for a join.

Method 2

I have encountered the same scenario. Here is the way how I solved it

models.py

from django.contrib.postgres.fields.jsonb import JSONField as JSONBField
location = JSONBField(default=list,null=True,blank=True)

insert

model_object.location = [{"locations" : "loc1","amount":Decimal(100.00)},{"locations" : "loc2","amount":Decimal(200.25)}]

update

model_object.location.append({"locations" : "loc1","amount":Decimal(100.00)})
model_object.save()

This worked for me in
Django – 2.0.2
Postgres – 9.5
psycopg2 – 2.7.4
python – 3.4.3

Method 3

You can sidestep this issue by using the JSONField as the column field type with a list as the root element.

from django.contrib.postgres.fields import JSONField
class MyDBArray(models.Model):
    array_data = models.JSONField(default=list)

my_db_array = MyDBArray(array_data=[1, 2, 3])
my_db_array.save()

You would need to validate in the save method that the array_data field is actually list-like.

Method 4

This was fixed in the latest unreleased version of Django 2.2a1

pip install Django==2.2a1

PS I believe that it will work with versions >= 2.2a1

Method 5

I guess the easiest way is to turn the field from an array of jsonfield into a jsonfield. Just add a key to the location_arr.

Related thread: ArrayField with JSONField as base_field in Django


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x