Джанго постгрес поле Json с цифровыми клавишами - PullRequest
0 голосов
/ 28 мая 2018

У меня есть модель с Postgres JSON Field.

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'})

Я хочу запросить все MyModel, чей ключ '10' начинается с '2017', поэтому я хочу написать:

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 было заключено в кавычки (что дало бы мне правильный ответ).

Спасибо!

1 Ответ

0 голосов
/ 28 мая 2018

Очень хакерское решение (используйте на свой страх и риск, протестировано в 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

Использование:

  1. Добавьте это в конец вашего settings.py:

    import patch_jsonb
    patch_jsonb.patch()
    
  2. Вместо __123__ поиска используйте __K123__ поиска - верхний регистр K будет удален этим патчем:

    MyModel.objects.filter(data__K10__startswith='2017')
    

И попробуйте не использовать числа в качестве ключей объектов jsonb ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...