本文介绍 Django 的 JSONField 如何通过 mssql-django 后端与 SQL Server 配合使用,包括支持的查找和限制。
先决条件
- SQL Server 2016 或更高版本(需要 JSON 函数)
-
mssql-django1.2 或更高版本
JSONField 如何映射到SQL Server
Django 的 JSONField 在 SQL Server 中映射为 nvarchar(max),并带有 JSON 检查约束。 后端使用SQL Server的内置 JSON 函数(JSON_VALUE、、JSON_QUERYISJSON)来实现查找和查询。
使用 JSONField 定义模型
将以下模型添加到 myapp/models.py. 本文中的示例使用模型 Item ,因此它们不会与 ProductDjango 快速入门中的模型冲突。
from django.db import models
class Item(models.Model):
name = models.CharField(max_length=100)
metadata = models.JSONField(default=dict)
tags = models.JSONField(null=True, blank=True)
生成并应用迁移,以便基础表存在于SQL Server中:
python manage.py makemigrations myapp
python manage.py migrate myapp
存储和检索 JSON 数据
使用 python manage.py shell.. 打开 Django shell。 在 >>> 提示符处,导入模型:
from myapp.models import Item
使用 JSON 数据创建记录:
item = Item.objects.create(
name="Widget",
metadata={"color": "blue", "weight": 1.5, "dimensions": {"height": 10, "width": 5}},
tags=["sale", "new"],
)
检索记录并访问 JSON 值:
item = Item.objects.get(name="Widget")
print(item.metadata["color"]) # "blue"
print(item.tags) # ["sale", "new"]
受支持的查找
mssql-django 后端支持以下 JSONField 查找:
键查找/索引查找
使用 Django 的双下划线语法访问嵌套 JSON 值:
# Filter by nested key value
Item.objects.filter(metadata__color="blue").values()
# Access nested objects
Item.objects.filter(metadata__dimensions__height=10).values()
包含
注释
mssql-django 后端不支持 contains 查找操作。 可改用 has_key 配合键路径查找:
# Instead of: Item.objects.filter(metadata__contains={"color": "blue"})
# Use key-path lookup:
Item.objects.filter(metadata__color="blue").values()
has_key
检查是否存在特定密钥:
Item.objects.filter(metadata__has_key="color").values()
has_keys
检查是否存在所有指定的密钥:
Item.objects.filter(metadata__has_keys=["color", "weight"]).values()
has_any_keys
检查是否存在任何指定的键:
Item.objects.filter(metadata__has_any_keys=["color", "size"]).values()
isnull
isnull 查找在 SQL Server 中具有特定行为:
# Returns objects where the key doesn't exist AND keys with None value
Item.objects.filter(metadata__color__isnull=True).values()
# Returns objects where the key exists and has a non-null value
Item.objects.filter(metadata__color__isnull=False).values()
注释
在 mssql-django 后端,如果某个密钥存在但具有 JSON null 值, has_key 则返回一个空的 QuerySet。 这与 PostgreSQL 不同,无论值如何,都会 has_key 返回 True 。
isnull=True 查找会返回键不存在的对象以及值为 null 的对象。
精确且无
exact 查找不支持 None 值。 以下查询返回空的 QuerySet:
# Returns empty QuerySet - use isnull lookup instead
Item.objects.filter(metadata__color=None).values()
请改用 isnull 查找来查找 null 值。
Limitations
-
使用 JSONField 进行批量更新:在将
bulk_update用于 JSONField 值时,存在一些特殊情况,尤其是在 Django 5.2 及更高版本中。 有关详细信息,请参阅 mssql-django 中的限制和不支持的功能。 - CASE WHEN 表达式:在 Django 5.2 及更高版本中,CASE WHEN 表达式中的某些 JSONField 操作可能会产生意外的结果。
-
exact with None:使用
isnull而不是exact来筛选 JSON null 值。 -
has_key 带有 null 值时:对于存在但值为
null的键,has_key会返回空 QuerySet。 -
JSON 字符串值中的文字引号字符:对包含文本
"字符(例如,metadata={"description": '"quoted"'})的 JSON 字符串值的相等性查找可能与存储的行不匹配。 包含引号字符的值能够正确存储,但却无法通过字段查找可靠地检索出来。