基于 JSONField 嵌套对象的 Django Rest Framework 过滤器

Django Rest Framework filter on the base of JSONField nested objects

我正在使用 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

It should return the MyModel records by props ID and should be able to return the JSON array of all the MyModel objects where the props ID by the GET request at /mymodel/props/<ID>. If the requested props does not exist then HTTP response code should be 404, otherwise, the response code should be 200. The JSON array should be sorted in ascending order by MyModel ID.

当我向这个视图发送请求时,它 returns 一个错误:

> 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 筛选对象?

请帮帮我! 提前致谢!

你应该使用

from django.contrib.postgres.fields import JSONField

而不是

import jsonfield

然后我认为一切都应该正常工作

您正在寻找的功能是可能的,不幸的是它不是那么简单。据我所知,jsonfield 包不支持它,但您必须使用 Postgres as your database backend and use its internal JSONField。我想你可以选择以下其中一项:

  • 切换到 django.contrib.postgres.fields.JSONField 并在所有环境中使用 Postgres 作为您的数据库后端(然后支持此类查找)
  • 使数据遵循一定的模式并将 JSON 字段更改为单独的模型并且 table
  • 使用混合存储解决方案和 JSON 个文档的专用解决方案
  • 将您需要查询的字段提取到您的模型中 - 启用查询,但将非结构化数据保留在 JSON 字段中。
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() 中设置 id 值:

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