class Blog:
values = JSONField(blank=True, default=list)
[
{
"id": 1,
"value": "31"
},
{
"id": 2,
"value": "Hello"
},
...
]
I need to get all objects where the id is 1 and value of that field is greater than 31.
I have tried q = queryset.filter(values__0__id=1, values__0__value_gte=31) but it works only for objects if an object that I need located only in first element.
Apparently, nowadays Django has not built-in support for array elements comparison for JSONField. Fortunately, Django allows to make a lot of custom staff. For example, Django's raw SQL feature.
And if you use PostgreSQL as your main DB, you can use JSON Processing Functions. The jsonb_array_elements() from JSON processing functions is pretty nice choice.
Combining features above, we can make a little workaround for your case:
# 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)
Pretty easy, isn't it? :)
Moreover, I believe it is possible to make your own queryset Lookup's for JSONField, extend queries as you want and etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With