Django postgres Json 带数字键的字段
Django postgres Json field with numeric keys
我有带有 postgres json 字段的模型。
class MyModel(models.Model):
data = JSONField(null=True)
那么,我做:
m1 = MyModel.objects.create(data={'10':'2017-12-1'})
m2 = MyModel.objects.create(data={'10':'2018-5-1'})
我想查询所有key'10'以'2017'开头的MyModel,所以我想写:
MyModel.objects.filter(data__10__startswith='2017')
问题是 10 被解释为整数,因此,在生成的查询中,它被视为列表索引而不是键。
无论如何要解决这个问题? (除了编写原始查询)。
这是生成的查询:
SELECT "systools_mymodel"."id", "systools_mymodel"."data" FROM "systools_mymodel" WHERE ("systools_mymodel"."data" ->> 10)::text LIKE '2017%' LIMIT 21;
我想引用 10(这会给我正确答案)。
谢谢!
一个非常骇人听闻的解决方案(使用风险自负,在 Django 2.0.5 下测试,保修无效...):
# patch_jsonb.py
from django.contrib.postgres.fields.jsonb import KeyTransform
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 %s %%s)" % (lhs, self.nested_operator), [
key_transforms] + params
try:
int(self.key_name)
except ValueError:
if self.key_name.startswith("K") and self.key_name[1:].isnumeric():
lookup = "'%s'" % self.key_name[1:]
else:
lookup = "'%s'" % self.key_name
else:
lookup = "%s" % self.key_name
return "(%s %s %s)" % (lhs, self.operator, lookup), params
def patch():
KeyTransform.as_sql = as_sql
用法:
将此添加到 settings.py
的底部:
import patch_jsonb
patch_jsonb.patch()
而不是 __123__
查找使用 __K123__
查找 - 大写 K
将被此补丁删除:
MyModel.objects.filter(data__K10__startswith='2017')
并考虑避免使用数字作为 jsonb 对象键...
我有带有 postgres json 字段的模型。
class MyModel(models.Model):
data = JSONField(null=True)
那么,我做:
m1 = MyModel.objects.create(data={'10':'2017-12-1'})
m2 = MyModel.objects.create(data={'10':'2018-5-1'})
我想查询所有key'10'以'2017'开头的MyModel,所以我想写:
MyModel.objects.filter(data__10__startswith='2017')
问题是 10 被解释为整数,因此,在生成的查询中,它被视为列表索引而不是键。 无论如何要解决这个问题? (除了编写原始查询)。
这是生成的查询:
SELECT "systools_mymodel"."id", "systools_mymodel"."data" FROM "systools_mymodel" WHERE ("systools_mymodel"."data" ->> 10)::text LIKE '2017%' LIMIT 21;
我想引用 10(这会给我正确答案)。
谢谢!
一个非常骇人听闻的解决方案(使用风险自负,在 Django 2.0.5 下测试,保修无效...):
# patch_jsonb.py
from django.contrib.postgres.fields.jsonb import KeyTransform
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 %s %%s)" % (lhs, self.nested_operator), [
key_transforms] + params
try:
int(self.key_name)
except ValueError:
if self.key_name.startswith("K") and self.key_name[1:].isnumeric():
lookup = "'%s'" % self.key_name[1:]
else:
lookup = "'%s'" % self.key_name
else:
lookup = "%s" % self.key_name
return "(%s %s %s)" % (lhs, self.operator, lookup), params
def patch():
KeyTransform.as_sql = as_sql
用法:
将此添加到
settings.py
的底部:import patch_jsonb patch_jsonb.patch()
而不是
__123__
查找使用__K123__
查找 - 大写K
将被此补丁删除:MyModel.objects.filter(data__K10__startswith='2017')
并考虑避免使用数字作为 jsonb 对象键...