Django 在 json 字段中注释特定键
Posted
技术标签:
【中文标题】Django 在 json 字段中注释特定键【英文标题】:Django annotate specific keys in json fields 【发布时间】:2017-06-26 04:02:45 【问题描述】:我正在使用 Django 1.9 和 Postgres 9.5。我有一个模型 (MyModel
) 和 JSONField
(django.contrib.postgres.fields
)。 JSON 值在模型中的所有对象中具有相同的结构。
"key1": int_val_1,
"key2": int_val_2
我想通过JSONField
中指定键的值对我的查询集进行排序。类似的东西
MyModel.objects.annotate(val=F('jsonfield__key1')).order_by('val')
这不起作用 - 我收到以下错误
Cannot resolve keyword 'key1' into field. Join on 'jsonfield' not permitted.
有没有我可以做到这一点?
【问题讨论】:
How to aggregate (min/max etc.) over Django JSONField data?的可能重复 【参考方案1】:对于 Django >= 1.11,您可以使用:
from django.contrib.postgres.fields.jsonb import KeyTextTransform
MyModel.objects.annotate(val=KeyTextTransform('key1', 'jsonfield')).order_by('val')
【讨论】:
如何将它用于嵌套的 json 字段?例如 jsonfield['key1']['key2'] KeyTextTransform 的嵌套字段目前有点 PITA - 例如MyModel.objects.annotate(val=KeyTextTransform('key1', 'jsonfield')).annotate(val1=KeyTextTransform('key2', 'val'))
.
因此,如果您有大量嵌套的 JSON 字段,那么 Django 查询也将嵌套在地狱中:.annotate( n=Cast( KeyTextTransform( 'value', KeyTextTransform( 'field2', KeyTextTransform( 'field1', 'data'), ), ), output_field=FloatField())
。 KeyTextTransform
的逻辑是按reverse顺序遍历字段。【参考方案2】:
这个问题的更新答案:
在撰写本文时(Django 3.1),您现在可以完全按照您希望的方式订购,而无需任何辅助函数:
MyModel.objects.order_by('jsonfield__key1')
【讨论】:
但是(v2.2)似乎有一个错误,所以这在注释中不起作用。以上是关于Django 在 json 字段中注释特定键的主要内容,如果未能解决你的问题,请参考以下文章