django - 不支持对 JSONField 的查找或不允许加入该字段
django - Unsupported lookup for JSONField or join on the field not permitted
我的模型中有一个 Json 字段 -
class Product(models.Model):
...
detailed_stock = JSONField(load_kwargs={'object_pairs_hook': collections.OrderedDict},default=dict)
我的数据库中有值,例如 -
{
"total":0,
"5[1]":0
}
我正在尝试过滤总计 = 0 的对象,为此我试过了 -
Product.objects.filter(detailed_stock__total = 0)
但它抛出错误 -
Unsupported lookup 'total' for JSONField or join on the field not permitted.
根据 documentation 允许使用以下代码。
这是完整的回溯-
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
上网查了没找到解决办法,求助。
我认为您正在使用 django-jsonfield as indicated by load_kwargs={'object_pairs_hook': collections.OrderedDict}
instead of django.contrib.postgres.fields.JSONField。
django-jsonfield
适用于不提供本机 dict
类型且基于字段本身的简单 TextField
. When you access the field value using product.detail_stock
the internally saved str
is converted to dict
using json.loads()
的数据库。因此,您只能使用 icontains
和 contains
等操作来查询该字段。
如果您使用 postgres 作为数据库,您可以充分利用 django.contrib.postgres.fields.JSONField
,如文档所述。但是您必须使用 django.contrib.postgres.fields import JSONField
.
导入正确的 JSONfield
mysql (package django-mysql) 也有一个解决方案。
如果您正在使用 Django 并且使用过:
from json_field import JSONField
那么您将无法受益于 SQL 查找。如上所述,JSONField 覆盖了
仅限文本字段。它验证 JSONformat 并转储为字符串。
class JSONField(models.TextField):
""" Stores and loads valid JSON objects. """
改为使用
from django.db import models
data = models.JSONField(null=True)
我的模型中有一个 Json 字段 -
class Product(models.Model):
...
detailed_stock = JSONField(load_kwargs={'object_pairs_hook': collections.OrderedDict},default=dict)
我的数据库中有值,例如 -
{
"total":0,
"5[1]":0
}
我正在尝试过滤总计 = 0 的对象,为此我试过了 -
Product.objects.filter(detailed_stock__total = 0)
但它抛出错误 -
Unsupported lookup 'total' for JSONField or join on the field not permitted.
根据 documentation 允许使用以下代码。
这是完整的回溯-
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
上网查了没找到解决办法,求助。
我认为您正在使用 django-jsonfield as indicated by load_kwargs={'object_pairs_hook': collections.OrderedDict}
instead of django.contrib.postgres.fields.JSONField。
django-jsonfield
适用于不提供本机 dict
类型且基于字段本身的简单 TextField
. When you access the field value using product.detail_stock
the internally saved str
is converted to dict
using json.loads()
的数据库。因此,您只能使用 icontains
和 contains
等操作来查询该字段。
如果您使用 postgres 作为数据库,您可以充分利用 django.contrib.postgres.fields.JSONField
,如文档所述。但是您必须使用 django.contrib.postgres.fields import JSONField
.
JSONfield
mysql (package django-mysql) 也有一个解决方案。
如果您正在使用 Django 并且使用过:
from json_field import JSONField
那么您将无法受益于 SQL 查找。如上所述,JSONField 覆盖了 仅限文本字段。它验证 JSONformat 并转储为字符串。
class JSONField(models.TextField):
""" Stores and loads valid JSON objects. """
改为使用
from django.db import models
data = models.JSONField(null=True)