caktus / django-filters-facet

A django-filter extension to refine search results using faceted navigation functionality.
https://facets.caktus-built.com
MIT License
28 stars 5 forks source link

Usage with Django Rest Framework #15

Open YuvantBesre opened 1 year ago

YuvantBesre commented 1 year ago

How do I use this using DRF's ListAPIView ?

FaridMalekpour commented 9 months ago

can you give more info to get help? I will do my best✌️

YuvantBesre commented 9 months ago

I just want to know whether we can use it in Django Rest Framework or not ? If yes, can you give me an example and showcase how to use this in our APIs ?

FaridMalekpour commented 9 months ago

let's create an example API using Django Rest Framework:

# serializers.py
from rest_framework import serializers
from .models import Film

class FilmSerializer(serializers.ModelSerializer):
    class Meta:
        model = Film
        fields = "__all__"

and this should be views.py:

from rest_framework import generics
from .models import Film
from .serializers import FilmSerializer
from django_filters.rest_framework import DjangoFilterBackend
from django_filters_facet import Facet, FacetedFilterSet

class FilmFilterSet(FacetedFilterSet):
    class Meta:
        model = Film
        fields = ["type", "release_year", "rating", "listed_in"]

    def configure_facets(self):
        self.filters["type"].facet = Facet()
        self.filters["rating"].facet = Facet()

class FilmListView(generics.ListAPIView):
    queryset = Film.objects.all()
    serializer_class = FilmSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = FilmFilterSet

and urls.py:

from django.urls import path
from .views import FilmListView

urlpatterns = [
    path('films/', FilmListView.as_view(), name='film-list'),
]

you can now access your API at the endpoint /films/ and use query parameters to filter the results based on the facets configured in your FilmFilterSet: this is an examole: GET /films/?type=action&rating=PG-13

This will return a list of films filtered by type "action" and rating "PG-13"

if there was any problem, let me know, but I think it fixes #15

stefanofusai commented 7 months ago

@Frenchcoder294 How would you display (or access) the facet counts in the DRF view? Thank you.

FaridMalekpour commented 6 months ago

@stefanofusai The facet counts returned by the django-filters-facet library are not directly accessible within the DRF view itself. but we can access them within the serializer class or override the get_queryset method of the viewset to manipulate the data before it's serialized.

like this:

Accessing facet counts in the Serializer

from rest_framework import serializers

class FilmSerializer(serializers.ModelSerializer):
    class Meta:
        model = Film
        fields = "__all__"

    def to_representation(self, instance):
        data = super().to_representation(instance)
        request = self.context.get('request')
        if request is not None and hasattr(request, 'facet_counts'):
            data['facet_counts'] = request.facet_counts
        return data

or like this:

Overriding the get_queryset method in the ViewSet:

from django_filters.rest_framework import APIView, filters

class FilmListView(generics.ListAPIView):
    queryset = Film.objects.all()
    serializer_class = FilmSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = FilmFilterSet

    def get_queryset(self):
        queryset = super().get_queryset()
        queryset = self.filter_queryset(queryset)
        if hasattr(queryset, 'facet_counts'):
            facet_counts = queryset.facet_counts
        return queryset

btw, sorry if it was late😉