Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Postgres:使用django查询json键的值_Python_Django_Django Models_Django Orm_Django Postgresql - Fatal编程技术网

Python Postgres:使用django查询json键的值

Python Postgres:使用django查询json键的值,python,django,django-models,django-orm,django-postgresql,Python,Django,Django Models,Django Orm,Django Postgresql,我需要在django 1.10中的postgres支持的jsonfield上的嵌套键上执行一个values/values\u列表查询 例如 如果它具有以下值: { 'lev1': { 'lev': 2 } } 我想运行一个类似于 AbcModel.objects.values('context__lev1__lev2').distinct() AbcModel.objects.values_list('context__lev1__lev2', flat=True).disti

我需要在django 1.10中的postgres支持的jsonfield上的嵌套键上执行一个values/values\u列表查询 例如

如果它具有以下值:

{
  'lev1': {
    'lev': 2
  }
}
我想运行一个类似于

AbcModel.objects.values('context__lev1__lev2').distinct()
AbcModel.objects.values_list('context__lev1__lev2', flat=True).distinct()

编辑:JSON字段是django.contrib.postgres.fields的官方django JSONField,这并不理想,但我可以通过将JSON字段添加为一个额外字段,然后调用该额外字段的值来实现这一点:

AbcModel.objects.extra(select={
    "extra_field": "context->'lev1'->'lev2'"
}).values('extra_field').distinct()
AbcModel.objects.extra(select={
    "extra_field": "context->'lev1'->'lev2'"
}).values_list('extra_field', flat=True).distinct()

所以我找到了一个解决方案,它适用于django 1.10及更高版本。 我使用KeyTransform注释和提取nexted键,并在其上创建了一个值列表

from django.contrib.postgres.fields.jsonb import KeyTransform
extracted_query = AbcModel.objects.annotate(lev1=KeyTransform('lev1', 'context')).annotate(lev2=KeyTransform('lev', 'lev1'))
此查询允许我将lev1和lev2用作模型中的普通字段,因此我可以对字段执行值、值列表或任何其他有效查询


Django 1.11允许将两个转换嵌套在一个注释中,但由于我已升级到1.11,因此无法确定嵌套的1.10,因此您面临的问题是什么?Django返回一个错误字段错误:无法将关键字“lev1”解析到字段中。不允许在“上下文”上加入。这是您数据库中的确切json表示形式吗?您的意思是什么?Postgres的数据类型是Jsonb。数据库的结构是相同的,这里显示的是什么?如何让->操作符工作?我想用它来代替大量的KeyTransform,但得到以下错误:django.db.utils.ProgrammingError:运算符不是唯一的:未知->未知行1:选择“步骤数据”->“步骤数据”->“车间”作为w FROM w…^提示:无法选择最佳候选运算符。您可能需要添加显式类型转换。@dirkgroten KeyTransform将使用->运算符,如果您使用单级提取,如“step_data”->“lev1”,它将使用>运算符,如果您使用嵌套或链接注释来提取嵌套数据,如“step_data”->“lev1”->“lev2”是的,我理解,谢谢您的回复。但我的问题是,当使用上面显示的显式select命令时。使用->运算符进行查询会显式抛出我所显示的错误运算符不是唯一的。是否将KeyTransform视为Django中非公共api的一部分?在Django 2中,文档中似乎没有提到它。它可以被视为一个非公共api,因为它在任何地方都没有文档记录,但同时,我发现postgres特定的东西没有Django的其他部分记录的那么好,但它不太可能改变,因为它会影响太多的东西,看看这个bug报告,它提出了相同的观点@Shaumux如果lev1键是动态的,我们如何评估它?这意味着lev是像从Subquery@NwawelAIroume我不知道你说的动态到底是什么意思,钥匙是动态的吗?您应该仍然能够使用Cast函数转换为JSON类型,并使用相同的方法,可能有很多嵌套调用though@Shaumaux我注意到Cast有助于提取整个dict。但我只想提取dict键的一个值。我想做一些类似annotatelev1=KeyTransformouterExternal\u model\u column\u value的事情,“context”
from django.contrib.postgres.fields.jsonb import KeyTransform
extracted_query = AbcModel.objects.annotate(lev1=KeyTransform('lev1', 'context')).annotate(lev2=KeyTransform('lev', 'lev1'))