在使用django框架时,有些model字段需要存储json对象,可以使用django-jsonfield中的JSONField。
一、安装依赖
pip install django-jsonfield==1.2.0
二、使用
from jsonfield import JSONField
class CollectConfig(models.Model):
ext_data = JSONField(_("额外数据"), default={})
config = JSONField(_("配置"), default=[])
可以存储
dict
,也可以存储list
。
三、筛选filter
举例:ext_data
中的数据如下
{
"bk_inst_name": "测试",
"inst_unique_id": "TEST",
"inst_account": "647397c2-f72a-4695-aee0-399d305b912a",
"inst_subscription": "dfaa4903-5af3-4f6b-a3d7-dafb4055d4f5"
}
- 单个字段筛选
此时,需要根据bk_inst_name
字段进行筛选。
CollectConfig.objects.filter(ext_data__contains={'bk_inst_name': '测试'})
如果需要忽略大小写:
CollectConfig.objects.filter(ext_data__icontains={'bk_inst_name': '测试'})
- 多个字段筛选
需要根据bk_inst_name
和inst_subscription
字段进行筛选, 必须全部符合。
$\color{red}{错误用法}$
CollectConfig.objects.filter(ext_data__icontains={'bk_inst_name': '测试', 'inst_subscription': 'dfaa4903-5af3-4f6b-a3d7-dafb4055d4f5'})
这种用法只有在
bk_inst_name
和inst_subscription
连在一起时才会起作用,否则就会查询不到。
我们可以使用Q,分开查询
from django.db.models import Q
q = Q(ext_data__icontains={'bk_inst_name': '测试'})
q.add(Q(ext_data__contains={ 'inst_subscription': 'dfaa4903-5af3-4f6b-a3d7-dafb4055d4f5'}), q.AND)
CollectConfig.objects.filter(q)
- 模糊查询(不支持)
django-jsonfield
用于不提供原生dict
类型且基于简单TextField
的数据库, 数据库中存储的是str
类型数据。当您使用CollectConfig.ext_data
访问字段值时,内部保存的str
将由字段本身使用json.loads()
转换为dict
。因此,您只能使用icontains
和contains
等操作来查询该字段。
例如:我们需要查询bk_inst_name
包含测试
两个字的数据。由于我们不确定测试
字段的具体位置,可能是xx测试xx
、测试xx
、 xx测试
,所以我们不能直接使用icontains
和contains
来查询。
如果是一些比较特殊的字符,可以结合sql语句来查询。