仅使用数字键查询JSONField

2024-10-06 15:29:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我从Django的文档中获取了以下示例,除了替换并添加了一个键'99':

>>> Dog.objects.create(name='Rufus', data={
... 'breed': 'labrador',
...     'owner': {
...         'name': 'Bob',
...         'other_pets': [{
...             'name': 'Fishy',
...         }],
...     },
... })
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', '99': 'FINDME',})

>>> Dog.objects.filter(data__breed='collie')
<QuerySet [<Dog: Meg>]>

我希望以下内容也能返回“Meg”狗:

^{pr2}$

但是,似乎因为我的键是一个整数,Django不能正确地处理这个问题。在jsonfildi中,python字符串有整数键吗?在


Tags: djangoname文档示例dataobjectscreate整数
2条回答

关于这个有一个wontfixDjango ticket。在

它是documented behavior

If the key is an integer, it will be interpreted as an index lookup in an array.

If the key you wish to query by clashes with the name of another lookup, use the jsonfield.contains lookup instead.

所以建议的解决方案是使用jsonfield.contains

Dog.objects.filter(data__contains={'99': 'FINDME'})

无论如何,我建议您避免在json字段中使用数字键,因为使用contains方法时,您无法执行startswith和其他类似的查找(请参见similar question),例如Dog.objects.filter(data__99__startswith='FIND')。在

看来没有一个好的选择。下面是django/contrib/postgres/fields中的一个片段/jsonb.py公司公司名称:

def as_sql(self, compiler, connection):
    key_transforms = [self.key_name]
    previous = self.lhs
    while isinstance(previous, KeyTransform):
        key_transforms.insert(0, previous.key_name)
        previous = previous.lhs
    lhs, params = compiler.compile(previous)
    if len(key_transforms) > 1:
        return "{} #> %s".format(lhs), [key_transforms] + params
    try:
        int(self.key_name)
    except ValueError:
        lookup = "'%s'" % self.key_name
    else:
        lookup = "%s" % self.key_name
    return "%s -> %s" % (lhs, lookup), params

由此看来,它试图将每个键转换为整数,并尽可能将其用作键。在

下面是一个可以按照您想要的方式进行查询的方法:

^{pr2}$

并以此为依据:

jsonb_integer_keys_to_str(Dog.objects.filter(data__99='FINDME'), 99)

这个解决方案过于具体,但在这种情况下仍然有效。它所做的就是修改postgres的sql并将引号放在正确的位置。在

相关问题 更多 >