ArrayField 中的 Django JSONField

Posted

技术标签:

【中文标题】ArrayField 中的 Django JSONField【英文标题】:Django JSONField inside ArrayField 【发布时间】:2017-04-29 06:58:54 【问题描述】:

我在使用带有 JSONField 的 ArrayField 插入字段时遇到问题。

models.py

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

插入

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

当我这样做时,我得到了

列“位置”的类型为 jsonb[],但表达式的类型为 text[]

第 1 行:...d" = 2517, "locations" = ARRAY['"loc...

提示:您需要重写或转换表达式。

所以我尝试使用以下方式转储它:

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

然后我得到了这个

第 1 行:...d" = 2517, "locations" = '["loc":...

DETAIL:“[”必须引入明确指定的数组维度。

我正在使用:

    Django 1.9 Python 2.7 Postgres 9.4.10 psycopg2 2.6.2

【问题讨论】:

这是known bug。 这已在Django==2.2a1 中修复 【参考方案1】:

数组

首先,让我们仔细看看Postgresql Arrays文档中的这段重要文字。

提示:数组不是集合;搜索特定的数组元素可以 数据库设计错误的标志。考虑使用一个单独的表 将成为数组元素的每个项目的行。这会更容易 进行搜索,并且可能会更好地扩展大量 元素。

大多数时候,您不应该使用数组。

JSONB

JSONB 在 Django 中作为 JSONField 类型可用。该字段比数组字段更具可扩展性和灵活性,并且可以更有效地进行搜索。但是,如果您发现自己一直在 JSONB 字段中搜索,上述关于数组的陈述对 JSONB 同样有效。

现在您的系统中有什么?一个包含 JSONB 字段的数组。这是一场等待发生的灾难。请标准化您的数据。

回顾

那么什么时候使用 ArrayField?

在极少数情况下,您不需要在该列中进行搜索,也不需要使用该列进行联接。

【讨论】:

谢谢。那么什么时候用ArrayField呢? 在您不需要在该列中搜索并且您不需要使用该列进行连接的极少数情况下。 我们使用 __contains 之类的自定义查找来进行搜索怎么样? docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/… 那不搜索数组字段? 哦,是的。我的错。谢谢!【参考方案2】:

我也遇到过同样的情况。这是我解决它的方法

models.py

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

插入

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

更新

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

这对我有用 Django - 2.0.2 Postgres - 9.5 psycopg2 - 2.7.4 蟒蛇 - 3.4.3

【讨论】:

现在如何在 JSONBField 中搜索特定位置,比如使用 locations="loc1"?【参考方案3】:

您可以通过使用 JSONField 作为列字段类型并以 list 作为根元素来回避这个问题。

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()

您需要在 save 方法中验证 array_data 字段实际上是类似列表的。

【讨论】:

【参考方案4】:

这已在最新的unreleased version of Django 2.2a1 中修复

pip install Django==2.2a1

PS 我相信它适用于版本>= 2.2a1

【讨论】:

【参考方案5】:

我想最简单的方法是将字段从 jsonfield 数组转换为 jsonfield。只需向 location_arr 添加一个键。

相关话题:ArrayField with JSONField as base_field in Django

【讨论】:

以上是关于ArrayField 中的 Django JSONField的主要内容,如果未能解决你的问题,请参考以下文章

Django Postgres ArrayField 与一对多关系

Django Query 获取 ArrayField 列的所有不同值的计数

如何查询 Django ArrayField 的长度?

Django Postgresql ArrayField 聚合

如何在 django rest 框架中设计 ArrayField?

Django Rest Framework 不接受 ArrayField POST