我遇到了一个Django项目的问题,其中JSONField最初用于存储数据.为了在保存数据时保持数据的顺序,我实现了一个排序功能.然而,我发现这种排序操作虽然对于显示是必要的,但在访问数据时似乎效率很低.

为了解决这个问题,我决定将JSONField转换为TextField,并使用json.dump来确保保留顺序,而不需要在每次访问数据时进行排序.

以前,模型上的字段是一个JSONfield,如下所示

class UserProfile(models.Model):
    ...
    data = models.JSONField(default=dict, null=True)

我决定迁移到Textfield,如下所示

class UserProfile(models.Model):
    ...
    data = models.TextField(blank=True, null=True)

不幸的是,虽然一些记录被成功地转换为正确的json格式,但转换过程并没有按预期进行.Django成功地将某些字段转换为正确的JSON字符串格式,但其他字段未正确处理.以下是格式错误的一个示例:

'{'is_valid': True, 'name': 'John Doe'}'

如上所述,Django将数据转换为字符串,但布尔值,如True,没有得到正确处理.

我正在就如何解决这个问题征求建议.目前,我正在考虑将单引号替换为双引号,并转换布尔值,如下所示:

data = '{'is_valid': True, 'name': 'John Doe'}'
formatted_data = data.replace("'", '"').replace('True', 'true').replace('False', 'false')

然而,我相信可能会有一个更优雅或更有效的解决方案.如有任何见解或建议,我将不胜感激.谢谢.

推荐答案

你不能把一本词典放在TextField位,或者至少不能不出现问题.事情就是这样发生的.

事实上,TextField会很乐意接受任何物体,但对它呼叫str(…),然后我们就完了.

事实上,在PythonIS中,{"a": "b"}将与str(…)一起转换为"{'a': 'b'}",这就是所保存的内容.但它不是有效的JSON.

然而,我相信可能会有一个更优雅或更有效的解决方案.

然而,您的解决方案有一些警告.你将True转换为true,但假设字符串是{'name': 'True foo'},那么现在我们有{'name': 'true foo'},所以我们不仅转换布尔值,而且到处都会弹出True,即使是给定的名称.

我认为我们面临的第一个问题是修复数据,并将其从back迁移到JSONField.我们可以通过以下方式做到这一点:

import json
from ast import literal_eval

to_update = []
for profile in UserProfile.objects.all():
    try:
        json.loads(profile.data)
    except ValueError:
        profile.data = json.dumps(literal_eval(profile.data))
        to_update.append(profile)
UserProfile.objects.bulk_update(to_update, fields=('data',))

这里我们判断数据是否可以解释为JSON,如果不能,我们将其解析为Python文字,并将其重写为JSON blob.

接下来,我们可以创建一个为我们执行加载和解析的定制字段,具体如下:

from django.db.models.fields import TextField


class OrderedJSONField(TextField):
    def to_python(self, value):
        value = super().to_python(value)
        if isinstance(value, str):
            return json.loads(value)
        return value

    def get_prep_value(self, value):
        return json.dumps(value)

然后我们可以使用该字段自动包装和展开JSON blob中的数据:

class UserProfile(models.Model):
    # …
    data = models.OrderedJSONField(default=dict, null=True)

we essentially here take advantage of the fact that Python's JSON library retains order in both serializing and deserializing, and that since , dictionaries are ordered.

但我们输了a lot分.事实上,无序返回条目的原因是因为现在的数据库支持JSON,它们以更紧凑的方式存储对象,并且还提供了通过查看JSON BLOB来过滤记录的工具,我们将失go 所有这些功能.问题是,JSON BLOB的顺序是否如此重要,以至于丢失信息,特别是从JavaScript does not always follows insertion order开始,最终可能会白费力气.

Python相关问答推荐

如何从aiohttp解决未关闭的客户端会话

为什么自定义pytree aux_data对于jnp.数组来说在.jit()之后跟踪,而对于np.数组来说则不是?

在Python中,什么表达相当于0x1.0p-53?

为什么我的(工作)代码(生成交互式情节)在将其放入函数中时不再工作?

合并同名列,但一列为空,另一列包含值

收件箱转换错误- polars.exceptions. ComputeHelp- pandera(0.19.0b3)带有polars

Twilio:CallInstance对象没有来自_的属性'

在编写要Excel的数据透视框架时修复标题行

使用matplotlib pcolormesh,如何停止从一行绘制的磁贴连接到上下行?

使用多个性能指标执行循环特征消除

具有多个选项的计数_匹配

为什么tkinter框架没有被隐藏?

当使用keras.utils.Image_dataset_from_directory仅加载测试数据集时,结果不同

输出中带有南的亚麻神经网络

如果条件不满足,我如何获得掩码的第一个索引并获得None?

在含噪声的3D点网格中识别4连通点模式

形状弃用警告与组合多边形和多边形如何解决

为一个组的每个子组绘制,

Django RawSQL注释字段

什么是合并两个embrame的最佳方法,其中一个有日期范围,另一个有日期没有任何共享列?