【问题标题】:DjangoFilterBackend filter in nested JSON filed嵌套 JSON 字段中的 DjangoFilterBackend 过滤器
【发布时间】: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 是否允许它从盒子中取出,或者我应该实现一种自定义方法?

【问题讨论】:

    标签: django django-rest-framework django-filter


    【解决方案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做同样的事情

      一些缺点:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 2021-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-18
        • 2018-06-05
        相关资源
        最近更新 更多