Django + Postgres:将JSON字符串直接保存到模型中作为JSON类型

时间:2016-11-14 16:46:31

标签: python json django postgresql pandas

我有一个Django模型,我想在其中保存无模式的键值元数据,所以我使用的是django.contrib.postgres.fields.JSONField

键值数据是Pandas系列,默认情况下不是JSON可序列化的(由于numpy.int64,numpy.float64类型),所以我使用方便的series.to_json()返回已经序列化的JSON字符串。

要将其保存到我的模型,我会在其上运行json.loads。但是我知道当数据保存到Postgres时会调用json.dumps

如何避免这种不必要的反序列化/重新序列化步骤?

代码示例:

def create_model(pandas_series):
    mdl = Model()
    metadata = pandas_series.to_json()  # gives a JSON string
    mdl.metadata = json.loads(metadata) # string->dict, then dict->string
    mdl.save()

1 个答案:

答案 0 :(得分:4)

瓶颈在哪里

我以编程方式创建了一个包含千个元素的字典,它看起来像这样:

d = {...," a240":240," a243":243," a242",...}

然后我json.loads(json.dumps(d))循环1000次。平均而言,1000次迭代需要510毫秒。

然后我创建了以下模型:

class JsonModel(models.Model):
    jfield = JSONField()

将字典1000次插入数据库,如下所示:

JsonModel.objects.create(jfield = d)

此操作平均需要21秒。因此,真正的瓶颈似乎是将数据保存到数据库而不是序列化反序列化步骤。

总而言之,保存到数据库的速度比json转储/加载大约慢40倍(但是你的里程将根据字典的大小,数据库上的负载等而变化)。

避免额外的序列化/去序列化步骤

基于上面的数字,不能转储/加载可能不值得。如果你热衷于尝试它,那么事情就是create a custom field。它可以像下面那样简单:

from django.contrib.postgres.fields import JSONField
class MyJsonField(JSONField):
    def get_prep_value(self, value):
        if isinstance(value, str):
            return value
        return super(MyJsonField,self).get_prep_value(value)

然后您的模型可以

class JsonModel(models.Model):
    metadata = MyJsonField()
    ....

然后在创建db记录时,您可以传入json序列化sting而不是调用json.loads

mdl.metadata = metadata # no string->dict, then dict->string