2

I have following structure:

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

with given list view

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

    search_fields = ['name']

    filterset_fields = {

        'some_data': ['exact']
    }

That i basically want to do is filter my result based on json value, something like mydomain/persons/all?social_media__Tiktok=true Does DjangoFilterBackend allows it from the box or i should implement kinda custom method?

2 Answers 2

3

I've implemented a custom method (or really overrid an existing method) that accomplishes what your trying to do without using django-filter.

One caveat is that here we use a ModelViewSet - so not entirely sure how this translates to a ListView. Otherwise, we will override override the get_queryset method of our ModelViewSet:

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

The request url will now look like, for example: my_website.com/api/persons?filter={"social_media__Tiktok":true}

Or more precisely: my_website.com/api/persons?filter=%7B%social_media__Tiktok%22:true%7D

Which can be built like:

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",
   ...
});

Some advantages:

  • no need to specify which fields can be filtered on each view class
  • write it once, use it everywhere
  • front end filtering looks exactly like django filtering
  • can do the same with exclude

Some disadvantages:

  • potential security risks if you want some fields to be non-filterable
  • less intuitive front-end code to query a table

Overall, this approach has been far more useful for me than any packages out there.

Sign up to request clarification or add additional context in comments.

Comments

0

You can write you, filter class, for filter social_media__Tiktok and name like this way. Hope this will help you to solve your problem.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.