带你尝鲜Django最新版重要更新JSONField的使用
Django最新版v3.1的主要更新之一便是完善了对JSON数据存储的支持,新增models.JSONField
和forms.JSONField
,可在所有受支持的数据库后端上使用
目前支持的数据库以及对应版本主要有MariaDB 10.2.7+
,MySQL 5.7.8+
,Oracle
,PostgreSQL
和SQLite 3.9.0+
,但个别Django的查询方法可能与部分数据库不兼容,例如contains
和contained_by
就不支持Oracle和SQLite数据库
JSONField使用
fromdjango.dbimportmodelsclassHero(models.Model):name=models.CharField(max_length=200)data=models.JSONField(null=True)def__str__(self):returnself.name
通过models.JSONField
可指定此字段为存储类型为JSON格式。null=True
表示此字段可以为空,这个NULL指的是SQL NULL,如果想存储为JsonNULL,则可以使用Value('null')
来实现
Hero.objects.create(name='coffee',data=Value('null'))
SQL NULL与JsonNULL的区别主要在is_null
的查询上不同,可以通过以下这个示例来理解下
>>>fromdjango.db.modelsimportValue>>>>>>Hero.objects.create(name='ops')<Hero:ops>>>>Hero.objects.create(name='coffee',data=Value('null'))<Hero:coffee>>>>>>>Hero.objects.filter(data=None)<QuerySet[<Hero:coffee>]>>>>Hero.objects.filter(data=Value('null'))<QuerySet[<Hero:coffee>]>>>>>>>Hero.objects.get(name='ops').data>>>Hero.objects.get(name='coffee').data>>>>>>Hero.objects.filter(data__isnull=True)<QuerySet[<Hero:ops>]>>>>Hero.objects.filter(data__isnull=False)<QuerySet[<Hero:coffee>]>
JSONField查询
Json字段的查询方法,通过下边这个示例演示说明
>>>Hero.objects.create(name='ops-',data={...'age':12,...'group':{...'name':'ow1',...'skill':[...{'name':'swim','rank':'A+'},...{'name':'shot','rank':None}...]...}...})<Hero:ops->>>>Hero.objects.create(name='ops-coffee',data={'age':16})<Hero:ops-coffee>
当想要查询age
为12
的数据时可以这样查询
>>>Hero.objects.filter(data__age=12)<QuerySet[<Hero:ops->]>
当想要查询group
的name
为ow1
的数据时可以这样查询
>>>Hero.objects.filter(data__group__name='ow1')<QuerySet[<Hero:ops->]>
当想要查询group
下skill
中第一个数据的name
值为swim
的数据时可以这样查询
>>>Hero.objects.filter(data__group__skill__0__name='swim')<QuerySet[<Hero:ops->]>
当想要查找包含group
键的所有数据时,可以通过has_key
来实现
>>>Hero.objects.filter(data__has_key='group')<QuerySet[<Hero:ops->]>
当想要查找同时包含group
键和age
键的所有数据时,可以通过has_keys
来实现
>>>Hero.objects.filter(data__has_keys=['group','age'])<QuerySet[<Hero:ops->]>
当想要查找包含group
键或者age
键的所有数据时,可以通过has_any_keys
来实现
>>>Hero.objects.filter(data__has_any_keys=['group','age'])<QuerySet[<Hero:ops->,<Hero:ops-coffee>]>
当想一次性查找包含age
为12
且group
的name
为ow1
的数据时,可以通过contains
来实现
>>>Hero.objects.filter(data__contains={'age':12,'group':{'name':'ow1'}})<QuerySet[<Hero:ops->]>
JSONField除了支持以上查询方式外,对于ORM所提供的大部分其他查询方式同样支持,例如icontains
,endswith
,iendswith
,iexact
,regex
,iregex
,startswith
,istartswith
,lt
,lte
,gt
,gte
,使用起来也是非常方便
>>>Hero.objects.filter(data__age__lte=12)<QuerySet[<Hero:ops->]>>>>>>>Hero.objects.filter(data__group__name__startswith='ow')<QuerySet[<Hero:ops->]>
SQLite3报错处理
我在Windows下开发测试时,当migrate
生成表的时候遇到了如下报错,这主要是因为SQLite不支持JSONFields导致的
SQLitedoesnotsupportJSONFields
解决方法为:
先去sqlite官网下载对应的DLL软件包/download.html
,然后替换掉当前使用的sqlite3.dll文件
。例如我的windows为64位版本,所以下载了sqlite-dll-win64-x64-3320300.zip
这个软件包,本地python的安装路径为C:\python36
,直接将C:\python36\DLLs\sqlite3.dll
用下载的软件包里的sqlite3.dll
文件替换,然后再次运行migrate
顺利创建了数据库表