嵌套 JSON 字段中的 DjangoFilterBackend 过滤器

Posted

技术标签:

【中文标题】嵌套 JSON 字段中的 DjangoFilterBackend 过滤器【英文标题】:DjangoFilterBackend filter in nested JSON filed 【发布时间】:2021-09-03 07:47:40 【问题描述】:

我有以下结构:

 
"some_data": 123,
"social_media": 
            
                "Tiktok": "true",
                "Instagram": "true"
                  
            
        
 

使用给定的列表视图

class PersonListView(generics.ListAPIView):
   
    serializer_class = AllPersonSerializer
    permission_class = permissions.IsAuthenticatedOrReadOnly
    filter_backends = (DjangoFilterBackend, SearchFilter)

    search_fields = ['name']

    filterset_fields = 

        'some_data': ['exact']
    

我基本上想做的是根据 json 值过滤我的结果,比如mydomain/persons/all?social_media__Tiktok=true DjangoFilterBackend 是否允许它从盒子中取出,或者我应该实现一种自定义方法?

【问题讨论】:

【参考方案1】:

您可以像这样为过滤器social_media__Tiktokname 编写过滤器类。希望这能帮助您解决问题。

import django_filters.rest_framework
import django_filters.filters

class FilterClass(django_filters.rest_framework.FilterSet):
    filtename = filters.CharFilter(method="my_custom_filter", label="Title of filtername")

   
    class Meta:
        model = ModelName
        fields = ("filtename",'name')

    def my_custom_filter(self, queryset, name, value):
        return ModelName.objects.filter(
            Q(social_media__Tiktok=value)
           
        )

class PersonListView(ListAPIView):
    permission_classes = permission
    serializer_class = serializers
    filterset_class = FilterClass

【讨论】:

【参考方案2】:

我已经实现了一个自定义方法(或真正覆盖现有方法),它可以使用django-filter 完成您尝试做的事情而不

需要注意的是,这里我们使用ModelViewSet - 所以不完全确定它如何转换为ListView。否则,我们将覆盖覆盖 ModelViewSetget_queryset 方法:

views.py

def BaseAPIView(...):

    ''' base view for other views to inherit '''

    def get_queryset(self):

        queryset = self.queryset

        # get filter request from client:
        filter_string = self.request.query_params.get('filter')

        # apply filters if they are passed in:
        if filters: 
            filter_dictionary = json.loads(filter_string)
            queryset = queryset.filter(**filter_dictionary)

        return queryset

请求 url 现在看起来像,例如:my_website.com/api/persons?filter="social_media__Tiktok":true

或者更准确地说:my_website.com/api/persons?filter=%7B%social_media__Tiktok%22:true%7D

可以这样构建:

script.js

// using ajax as an example:
var filter = JSON.stringify(
  "social_media__Tiktok" : true
);

$.ajax(
   "url" : "my_website.com/api/persons?filter=" + filter,
   "type" : "GET",
   ...
);

一些优点:

无需指定每个视图类可以过滤哪些字段 一次编写,随处使用 前端过滤看起来就像 django 过滤 可以用exclude做同样的事情

一些缺点:

如果您希望某些字段不可过滤,则可能存在安全风险 查询表的前端代码不太直观

总的来说,这种方法对我来说比现有的任何软件包都有用得多。

【讨论】:

以上是关于嵌套 JSON 字段中的 DjangoFilterBackend 过滤器的主要内容,如果未能解决你的问题,请参考以下文章

使用 spark 读取和访问 json 文件中的嵌套字段

更新Couchbase中的嵌套json数组字段

如何从 MySQL 中的数字键嵌套 JSON 字段中提取值

如何使用 AWS Glue 从嵌套 json 字段/结构中的 DynamicFrame 访问数据

使用 Spark 访问嵌套在结构中的 json 数组

Rails 仅将模型嵌套关联中的某些字段呈现为 json