django - Unsupported lookup for JSONField or join on the field not permitted

爱⌒轻易说出口 提交于 2021-02-09 11:10:16

问题


I am having a Json field in my models as -

class Product(models.Model):
    ...
    detailed_stock           = JSONField(load_kwargs={'object_pairs_hook': collections.OrderedDict},default=dict)

I am having values in my database like -

{
  "total":0,
  "5[1]":0
}

I am trying to filter objects with total = 0, for that I tried -

Product.objects.filter(detailed_stock__total = 0) but it throws error -

Unsupported lookup 'total' for JSONField or join on the field not permitted.

as per the documentation the following code is permitted.

this is full traceback-

Traceback (most recent call last):
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
    response = get_response(request)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\views\generic\base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\braces\views\_access.py", line 102, in dispatch
    request, *args, **kwargs)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\views\generic\base.py", line 89, in dispatch
    return handler(request, *args, **kwargs)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\views\generic\list.py", line 142, in get
    self.object_list = self.get_queryset()
  File "c:\Users\lenovo\Desktop\My_Django_Stuff\bekaim\accounts\views.py", line 142, in get_queryset
    queryset = Product.objects.filter(detailed_stock__total = 0)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\query.py", line 836, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\query.py", line 854, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\sql\query.py", line 1253, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\sql\query.py", line 1271, in _add_q
    current_negated, allow_joins, split_subq)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\sql\query.py", line 1277, in _add_q
    split_subq=split_subq,
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\sql\query.py", line 1215, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\sql\query.py", line 1069, in build_lookup
    lhs = self.try_transform(lhs, name)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\sql\query.py", line 1115, in try_transform
    (name, lhs.output_field.__class__.__name__))
django.core.exceptions.FieldError: Unsupported lookup 'total' for JSONField or join on the field not permitted.
[31/Dec/2018 16:13:37] "GET /accounts/product-list/?clean=outofstock HTTP/1.1" 500 150927

I searched on internet but unable to find the solution, please help.


回答1:


I think you are using django-jsonfield as indicated by load_kwargs={'object_pairs_hook': collections.OrderedDict} instead of django.contrib.postgres.fields.JSONField.

django-jsonfield is for databases which don't offer a native dict type and is based on a simple TextField. When you access the field value using product.detail_stock the internally saved str is converted to dict using json.loads() by the field itself. Hence you can only use operations like icontains and contains for querying that field.

If you are using postgres as a database, you are able to take full advantage of django.contrib.postgres.fields.JSONField as the documentation states. But you have to import the correct JSONfield by using django.contrib.postgres.fields import JSONField.

There is a solution for mysql (package django-mysql) too.




回答2:


If you are using Django and have used:

from json_field import JSONField

Then you can not benefit the SQL lookup. As mentioned above, JSONField overrides the TextField only. It validates the JSONformat and dumps as string.

class JSONField(models.TextField):
    """ Stores and loads valid JSON objects. """

Instead use

from django.db import models
data = models.JSONField(null=True)


来源:https://stackoverflow.com/questions/53986686/django-unsupported-lookup-for-jsonfield-or-join-on-the-field-not-permitted

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!