9

Django ORM中原生JSONField的使用方法

 2 years ago
source link: https://blog.ops-coffee.cn/s/ukpmc39c2ysi_8j9aduoug
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Django ORM中原生JSONField的使用方法

带你尝鲜Django最新版重要更新JSONField的使用

Django最新版v3.1的主要更新之一便是完善了对JSON数据存储的支持,新增models.JSONFieldforms.JSONField,可在所有受支持的数据库后端上使用

目前支持的数据库以及对应版本主要有MariaDB 10.2.7+,MySQL 5.7.8+,Oracle,PostgreSQLSQLite 3.9.0+,但个别Django的查询方法可能与部分数据库不兼容,例如containscontained_by就不支持Oracle和SQLite数据库

JSONField使用

from django.db import models

class Hero(models.Model):
    name = models.CharField(max_length=200)
    data = models.JSONField(null=True)

    def __str__(self):
        return self.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的查询上不同,可以通过以下这个示例来理解下

>>> from django.db.models import Value
>>>
>>> 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-coffee.cn', data={
...     'age': 12,
...     'group': {
...         'name': 'ow1',
...         'skill': [
...             {'name': 'swim', 'rank': 'A+'},
...             {'name': 'shot', 'rank': None}
...         ]
...     }
... })
<Hero: ops-coffee.cn>
>>> Hero.objects.create(name='ops-coffee', data={'age':16})
<Hero: ops-coffee>

当想要查询age12的数据时可以这样查询

>>> Hero.objects.filter(data__age=12)
<QuerySet [<Hero: ops-coffee.cn>]>

当想要查询groupnameow1的数据时可以这样查询

>>> Hero.objects.filter(data__group__name='ow1')
<QuerySet [<Hero: ops-coffee.cn>]>

当想要查询groupskill中第一个数据的name值为swim的数据时可以这样查询

>>> Hero.objects.filter(data__group__skill__0__name='swim')
<QuerySet [<Hero: ops-coffee.cn>]>

当想要查找包含group键的所有数据时,可以通过has_key来实现

>>> Hero.objects.filter(data__has_key='group')
<QuerySet [<Hero: ops-coffee.cn>]>

当想要查找同时包含group键和age键的所有数据时,可以通过has_keys来实现

>>> Hero.objects.filter(data__has_keys=['group','age'])
<QuerySet [<Hero: ops-coffee.cn>]>

当想要查找包含group键或者age键的所有数据时,可以通过has_any_keys来实现

>>> Hero.objects.filter(data__has_any_keys=['group','age'])
<QuerySet [<Hero: ops-coffee.cn>, <Hero: ops-coffee>]>

当想一次性查找包含age12groupnameow1的数据时,可以通过contains来实现

>>> Hero.objects.filter(data__contains={'age':12,'group': {'name': 'ow1'}})
<QuerySet [<Hero: ops-coffee.cn>]>

JSONField除了支持以上查询方式外,对于ORM所提供的大部分其他查询方式同样支持,例如icontains,endswith,iendswith,iexact,regex,iregex, startswith,istartswith,lt,lte,gt,gte,使用起来也是非常方便

>>> Hero.objects.filter(data__age__lte=12)
<QuerySet [<Hero: ops-coffee.cn>]>
>>>
>>> Hero.objects.filter(data__group__name__startswith='ow')
<QuerySet [<Hero: ops-coffee.cn>]>

SQLite3报错处理

我在Windows下开发测试时,当migrate生成表的时候遇到了如下报错,这主要是因为SQLite不支持JSONFields导致的

SQLite does not support JSONFields

解决方法为:

先去sqlite官网下载对应的DLL软件包https://www.sqlite.org/download.html,然后替换掉当前使用的sqlite3.dll文件。例如我的windows为64位版本,所以下载了sqlite-dll-win64-x64-3320300.zip这个软件包,本地python的安装路径为C:\python36,直接将C:\python36\DLLs\sqlite3.dll用下载的软件包里的sqlite3.dll文件替换,然后再次运行migrate顺利创建了数据库表


能看到这里一定是真爱,关注一下吧

wx.sou1.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK