Django Postgresql JsonField запрос связанных ключей словаря

Часть моей модели, которая использует поле Django Model, выглядит следующим образом:

class SalesModel(models.Model):
    some_data = models.PositiveIntegerField(db_index=True)
    some_other_data = models.CharField(max_length=50)
    json_data = JSONField(blank=True, null=True)

Теперь следующий формат поля JsonData:

[{"id": val, "contribution": "some_val", }, {"id": some_val, "contribution": "some_other_val",}, {"id": other_val, "contribution": "some_another_val"}]

то есть формат:

 [{'id':XX, 'contribution':XX},{'id':YY, 'contribution':YY},{'id':ZZ, 'contribution':ZZ}]

В настоящее время я могу отфильтровать таблицу Django по значению идентификатора. Теперь я хотел бы узнать, какой вклад это конкретное удостоверение личности.

Например, если val = 1, я хотел бы отфильтровать модель SalesModel, в которой есть JsonField с id = 1, и я хочу показать связанный вклад. Таким образом, это означало бы, что из 3-х возможных словарей (согласно конструкции поля) я бы показывал только один словарь (отфильтрованный по ключу "ID" этого словаря). Это будет означать, что если у 2-го словаря совпадающий идентификатор, показывать только 2-й вклад, если 1-й совпадает, показывать только 1-й вклад и аналогично для 3-го словаря.

Есть ли способ, который можно сделать?

3 ответа

Решение

Вы могли бы реструктурировать свой JSONField иначе говоря, указав, где ключ, пары значений id: contribution непосредственно. Таким образом, вы могли бы использовать has_key фильтр и KeyTransform будет работать, так как я не уверен, что он работает на множестве диктов. Итак, если ваш json_data выглядит так:

{1: 'xx', 3: 'yy', 9: 'zz'}

Вы можете запросить этот способ, основываясь на Vanojx1:

SalesModel.filter(json_data__has_key=id)\
    .annotate(contrib=KeyTransform(id, 'json_data')\
    .values('contrib')

В качестве альтернативы, используя raw jsonb в postgresql:

SalesModel.filter(json_data__has_key=id)\
    .extra(select={'contrib': "json_data->{0}".format(id)})\
    .values('contrib')

Это должно работать DOC

SalesModel.objects.filter(json_data__id=1).values('id', 'json_data__contribution')

Я полагаю, да. Если я правильно понял, у вас будет соответствующий идентификатор или список идентификаторов. Так что, если ваш идентификатор 2:

my_id = 2
dict1 = [{"id":1, "contribution":10},{"id":2, "contribution":20},{"id":3, "contribution":30}] 
for i in dict1:
    if i["id"] == my_id:
        print(i["contribution"])
Другие вопросы по тегам