Search code examples
pythondjangodjango-rest-frameworkdjango-filter

Filtering on the basis of tags in Django Rest Framework


I have an array of tags as a model field, I want to filter out based on those array elements. here is the model in which tag field is an array type I guess.

class Mineral(models.Model):
    name=models.CharField(max_length=500)
    tags=TaggableManager()
    def __unicode__(self):
        return self.name

Now in my view, I want to filter out based on this tag field I can do that using Django way like this

class MineralList(APIView):
    queryset = Mineral.objects.all()
    serializer_class = MineralSerializer

    permission_classes = [AllowAny]

    def get(self, request, format=None):
        mineral = Mineral.objects.all()

        tags = request.query_params.get('tags', None)
        name= request.query_params.get('name',None)

        if tags is not None:
            tags = tags.split(',')
            mineral = mineral.filter(tags__name__in=tags).distinct()
        if name:
            mineral = mineral.filter(name=name)
        serializer = MineralSerializer(mineral, many=True)
        return Response(serializer.data)

How can I do that in REST way using filter backends and Filter class


Solution

  • You could create the FilterSet class like this:

    from django_filters.rest_framework import FilterSet, filters
    from django_filters.widgets import CSVWidget
    
    
    class MineralFilterSet(FilterSet):
        tags = filters.CharFilter(distinct=True, widget=CSVWidget, method='filter_tags')
        name = filters.CharFilter()
    
        class Meta:
            model = Mineral
            fields = ['name', 'tags']
    
        def filter_tags(self, queryset, name, value):
            return queryset.filter(tags__name__in=value)
    

    And your view should be like this:

    from django_filters.rest_framework import DjangoFilterBackend
    
    class MineralList(ListAPIView):
        queryset = Mineral.objects.all()
        serializer_class = MineralSerializer
    
        permission_classes = [AllowAny]
    
        filter_backends = (DjangoFilterBackend,)
        filter_class = MineralFilterSet