Фильтр Django Rest Framework на основе вложенных объектов JSONField - PullRequest
0 голосов
/ 18 февраля 2019

Я работаю над проектом с использованием 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 ]

0 голосов
/ 18 февраля 2019

Возможность, которую вы ищете, к сожалению, не так проста.Насколько я знаю, он не поддерживается пакетом 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)
0 голосов
/ 18 февраля 2019

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

from django.contrib.postgres.fields import JSONField

вместо

import jsonfield

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

...