我从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>]>
我希望以下内容也能让&#34; Meg&#34;狗:
Dog.objects.filter(data__99='FINDME')
然而,似乎因为我的键是一个整数,Django没有正确处理它。我如何在python jsonfields中使用字符串的整数键?
答案 0 :(得分:1)
有一个wontfix
Django ticket。
如果键是整数,它将被解释为数组中的索引查找。
如果要查询的键与另一个查询的名称冲突,请使用jsonfield.contains查找。
所以建议的解决方案是使用jsonfield.contains:
Dog.objects.filter(data__contains={'99': 'FINDME'})
无论如何,我建议您避免在json字段中使用数字键,因为使用contains
方法无法执行startswith
和其他类似的查找(请参见similar question),例如{{1} }。
答案 1 :(得分:0)
看起来不是一个不错的选择。这是来自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
从这看起来,它似乎试图将每个键变成一个整数,并在可能的情况下将其用作键。
以下是您可以按照自己的方式进行查询的黑客行为:
def jsonb_integer_keys_to_str(qs, key):
return qs.model.objects.raw(qs.query.__str__().replace('-> {}'.format(key), "-> '{}'".format(key)))
并按原样使用:
jsonb_integer_keys_to_str(Dog.objects.filter(data__99='FINDME'), 99)
此解决方案过于具体,但在这种情况下可以使用。它正在做的是修改postgres sql并将引号放在正确的位置。