codecamp

Django4.0 执行查询-查询JSONField

JSONField ​里的查找实现是不一样的,主要因为存在键转换。为了演示,我们将使用下面这个例子:

from django.db import models class Dog(models.Model): name = models.CharField(max_length=200) data = models.JSONField(null=True) def __str__(self): return self.name

保存和查询None值

与其他字段一样,将 ​None ​作为字段的值存储为 SQL 的 ​NULL​。虽然不建议这样做,但可以使用 ​Value('null')​ 来存储 JSON 的 ​null ​值。
无论存储哪种值,当从数据库检索时,JSON 标量 ​null ​的 Python 表示法与 SQL 的 ​NULL ​相同,即 ​None​。因此,可能很难区分它们。
这只适用于 ​None ​值作为字段的顶级值。如果 ​None ​被保存在列表或字典中,它将始终被解释为 JSON 的 ​null ​值。
当查询时,​None ​值将一直被解释为 JSON 的 ​null​。要查询 SQL 的 ​NULL​,请使用 ​isnull ​:

>>> Dog.objects.create(name='Max', data=None) # SQL NULL. <Dog: Max> >>> Dog.objects.create(name='Archie', data=Value('null')) # JSON null. <Dog: Archie> >>> Dog.objects.filter(data=None) <QuerySet [<Dog: Archie>]> >>> Dog.objects.filter(data=Value('null')) <QuerySet [<Dog: Archie>]> >>> Dog.objects.filter(data__isnull=True) <QuerySet [<Dog: Max>]> >>> Dog.objects.filter(data__isnull=False) <QuerySet [<Dog: Archie>]>

除非你确定要使用 SQL 的 ​NULL ​值,否则请考虑设置 ​null=False​ 并为空值提供合适的默认值,例如 ​default=dict​ 。

注意:保存 JSON 的 ​null ​值不违反 Django 的 ​null=False​ 。

键、索引和路径转换

为了查询给定的字典键,请将该键作为查询名:

>>> Dog.objects.create(name='Rufus', data={ ... 'breed': 'labrador', ... 'owner': { ... 'name': 'Bob', ... 'other_pets': [{ ... 'name': 'Fishy', ... }], ... }, ... }) <Dog: Rufus> >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': None}) <Dog: Meg> >>> Dog.objects.filter(data__breed='collie') <QuerySet [<Dog: Meg>]>

可以将多个键链接起来形成一个路径查询:

>>> Dog.objects.filter(data__owner__name='Bob') <QuerySet [<Dog: Rufus>]>

如果键是个整型,那么它将在数组中被解释成一个索引:

>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy') <QuerySet [<Dog: Rufus>]>

如果要查询的键与另一个查询的键名冲突,请改用 ​contains ​来查询。
如果查询时缺少键名,请使用 ​isnull ​查询:

>>> Dog.objects.create(name='Shep', data={'breed': 'collie'}) <Dog: Shep> >>> Dog.objects.filter(data__owner__isnull=True) <QuerySet [<Dog: Shep>]>

上面给出的例子隐式地使用了 ​exact ​查找。​Key​,​Index​和​Path​转换也可以用:​icontains​、​endswith​、​iendswith​、​iexact​、​regex​、​iregex​、​startswith​、​istartswith​、​lt​、​lte​、​gt​、​gte ​以及 包含与键查找 。

由于​Key-Path​查询的工作方式,​exclude()​ 和 ​filter()​ 不能保证产生详尽的集合。如果你想包含没有路径的对象,请添加 ​isnull ​查找。

包含与键查询

contains

JSONField ​上的 ​contains ​查找已被覆盖。返回的对象是那些给定的键值对都包含在顶级字段中的对象。例如:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'}) <Dog: Rufus> >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'}) <Dog: Meg> >>> Dog.objects.create(name='Fred', data={}) <Dog: Fred> >>> Dog.objects.filter(data__contains={'owner': 'Bob'}) <QuerySet [<Dog: Rufus>, <Dog: Meg>]> >>> Dog.objects.filter(data__contains={'breed': 'collie'}) <QuerySet [<Dog: Meg>]>

contained_by

这是 ​contains ​查找逆过程——返回的对象将是那些传递的值中的子集在对象上的键值对。例如:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'}) <Dog: Rufus> >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'}) <Dog: Meg> >>> Dog.objects.create(name='Fred', data={}) <Dog: Fred> >>> Dog.objects.filter(data__contained_by={'breed': 'collie', 'owner': 'Bob'}) <QuerySet [<Dog: Meg>, <Dog: Fred>]> >>> Dog.objects.filter(data__contained_by={'breed': 'collie'}) <QuerySet [<Dog: Fred>]>

has_key

返回给定的键位于数据顶层的对象。例如:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'}) <Dog: Rufus> >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'}) <Dog: Meg> >>> Dog.objects.filter(data__has_key='owner') <QuerySet [<Dog: Meg>]>

has_keys

返回所有给定的键位于数据顶层的对象。例如:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'}) <Dog: Rufus> >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'}) <Dog: Meg> >>> Dog.objects.filter(data__has_keys=['breed', 'owner']) <QuerySet [<Dog: Meg>]>

has_any_keys

返回任何给定的键位于数据顶层的对象。例如:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'}) <Dog: Rufus> >>> Dog.objects.create(name='Meg', data={'owner': 'Bob'}) <Dog: Meg> >>> Dog.objects.filter(data__has_any_keys=['owner', 'breed']) <QuerySet [<Dog: Rufus>, <Dog: Meg>]>


Django4.0 执行查询-检索对象
Django4.0 执行查询-通过Q对象完成复杂查询
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

Django4.0 模型和数据库

Django4.0 处理HTTP请求

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }