Фильтр Django Rest Framework на основе вложенных объектов JSONField

Я работаю над проектом с использованием Python(3), Django(1.11) и DRF, в котором я должен фильтровать данные на основе json поле объекта, которое сохраняется как JSONFIELD в модели дб.

Вот что я попробовал:

model.py:

from django.db import models
import jsonfield

class MyModel(models.Model):
    id = models.CharField(primary_key=True, max_length=255)
    type = models.CharField(max_length=255)
    props = jsonfield.JSONField()
    repo = jsonfield.JSONField()
    created_at = models.DateTimeField()

serializers.py:

class MyModelSerializer(serializers.ModelSerializer):
    props = serializers.JSONField()
    repo = serializers.JSONField()

    class Meta:
        model = EventModel
        fields = "__all__"

Json object:

{
  "id":4633249595,
  "type":"PushEvent",
  "props":{
    "id":4276597,
    "login":"iholloway",
    "avatar_url":"https://avatars.com/4276597"
  },
  "repo":{
    "id":269910,
    "name":"iholloway/aperiam-consectetur",
    "url":"https://github.com/iholloway/aperiam-consectetur"
  },
  "created_at":"2016-04-18 00:13:31"
}

views.py:

class PropsEvents(generics.RetrieveAPIView):
    serializer_class = MyModelSerializer

    def get_object(self):
        print(self.request.parser_context['kwargs']['id'])
        queryset = MyModel.objects.filter(data__props__id=self.request.parser_context['kwargs']['id'])
        obj = get_object_or_404(queryset)
        return obj

Он должен вернуть записи MyModel по props ID и должен быть в состоянии вернуть массив JSON всех MyModel objects где props ID по запросу GET на /mymodel/props/<ID>, Если запрошенный props не существует, тогда код ответа HTTP должен быть 404, в противном случае код ответа должен быть 200. Массив JSON должен быть отсортирован в порядке возрастания по идентификатору MyModel.

Когда я отправил запрос в это представление, он возвращает ошибку:

django.core.exceptions.FieldError: Unsupported lookup 'id' for JSONField or join on the field not permitted.
[18/Feb/2019 10:37:39] "GET /events/actors/2790311/ HTTP/1.1" 500 16210

Итак, как я могу отфильтровать объекты на основе id of props?

Помоги мне, пожалуйста! Заранее спасибо!

2 ответа

Решение

Функция, которую вы ищете, возможна, к сожалению, это не так просто. Насколько я знаю, это не поддерживается jsonfield пакет, но вместо этого вам придется использовать Postgres в качестве базы данных и использовать его внутренний JSONField. Я думаю, что вы можете выбрать один из следующих:

  • переключиться на django.contrib.postgres.fields.JSONField и использовать Postgres в качестве базы данных вашей базы данных во всех средах (а затем поддерживать такие поиски)
  • заставить данные следовать определенной схеме и изменить JSONField на отдельную модель и таблицу
  • использовать гибридное решение для хранения с выделенным решением для документов JSON
  • Извлеките поля, к которым необходимо выполнить запрос, в вашу модель - включив запрос, но сохранив неструктурированные данные в JSONField.
class MyModel(models.Model):
    id = models.CharField(primary_key=True, max_length=255)
    type = models.CharField(max_length=255)
    props = jsonfield.JSONField()
    props_id = models.IntegerField(null=True)
    repo = jsonfield.JSONField()
    repo_id = models.IntegerField(null=True)
    created_at = models.DateTimeField()

А затем установите значения идентификатора вручную или в save() модели:

def save(self, *args, **kwargs):
    self.repo_id = self.repo.get("id")
    self.props_id = self.props.get("id")
    return super().save(*args, **kwargs)

Вы должны использовать

from django.contrib.postgres.fields import JSONField

Вместо

import jsonfield

И после этого я думаю, что все должно работать правильно

Другие вопросы по тегам