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 字段中注释特定键的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中注释 values() 查询

解析 JSON 文件数据后,在结果 XML 中添加注释

如何在 Django QuerySet 中注释两个字段的最大值

带有字段比较结果的django注释查询集

使用注释时在 Django 中显示选择字段的名称

如何使用注释在 Django ORM 中创建通知日期字段