django - Django JsonField 按两个字段过滤
问题描述
class Blog:
values = JSONField(blank=True, default=list)
[
{
"id": 1,
"value": "31"
},
{
"id": 2,
"value": "Hello"
},
...
]
我需要获取 id 为 1 且该字段的值大于 31 的所有对象。我已经尝试过q = queryset.filter(values__0__id=1, values__0__value_gte=31)
,但它仅适用于我需要的对象仅位于第一个元素中的对象。
解决方案
显然,现在Django
还没有对数组元素比较的内置支持JSONField
。幸运的是,Django
允许制作大量自定义人员。例如,Django
的原始 SQL功能。
如果你使用 PostgreSQL 作为你的主数据库,你可以使用JSON 处理函数。jsonb_array_elements()
from JSON 处理函数是相当不错的选择。
结合上述功能,我们可以为您的情况做一些解决方法:
# Create method that uses raw SQL within your `objects` Model Manager.
# Create your own filters as you want. This example should be improved
# and handle exception cases of course.
def filter_blogs_json(json_field, sql_operator, value):
return Blog.objects.raw(f"SELECT id, data FROM yourappname_blog CROSS JOIN jsonb_array_elements(values) AS data WHERE (data->'{json_field}')::numeric {sql_operator} {value};")
# You can get raw objects queryset
raw_blogs_qs = filter_blogs_json('value', '>=', 31)
# Then you can process it anyway you want
filtered_blog_ids = [b.id for b in raw_blogs_qs]
queryset = Blog.objects.filter(...).filter(id__in=filtered_blog_ids)
很容易,不是吗?:)
此外,我相信可以制作自己的查询集Lookup的 for JSONField
,根据需要扩展查询等。
推荐阅读
- python - Python 通过键入检查 isinstance
- java - Use replaceAll() to replace all occurrences of characters in string
- java - 在 JavaFX 应用程序中保持 ServerSocket 处于活动状态
- javascript - Doc-type html/w3c 打破 css
- java - java.util.ConcurrentModificationException Error while trying to use iterator
- intellij-idea - How to change project title in IntelliJ IDEA?
- raspberry-pi3 - 我正在使用带有 PiCamera v2.1 的 Tinker Board。如何设置捕获图像的颜色格式以及如何设置曝光参数?
- javascript - How can i replace a
with a with jquery?
- java - 使用 WS-Security 签署 SAAJ SOAPMessage
- elasticsearch - 如何释放 Elasticsearch 集群中的空间