Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to filter in a django mptt-model using django-filters

I have models.py

from mptt.models import MPTTModel, TreeForeignKey

class Category(MPTTModel):
    name = models.CharField(max_length = 255, null = False, blank = False)
    parent = TreeForeignKey('self', on_delete = models.CASCADE, blank = False, null = True, related_name = 'children')
    # other fields

class Product(models.Model):
    category = models.ForeignKey(Category, on_delete = models.SET_NULL, null = True, blank = True, related_name = 'products')
    # other fields
    

views.py

class ProductAPIView(generics.GenericAPIView):

    serializer_class = ProductSerializer
    queryset = Product.objects.all()
    filter_backends = [ DjangoFilterBackend ]
    filterset_class = ProductFilter

    def get(self, request):
        products = self.filter_queryset(self.get_queryset())
        serializer = self.serializer_class(products, many = True)
        return Response(serializer.data)

class CategoryAPIView(generics.GenericAPIView):

    serializer_class = CategorySerializer
    queryset = Category.objects.root_nodes()

filters.py

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

from django_filters import FilterSet, CharFilter, NumberFilter
from .models import Product

class ProductFilter(FilterSet):
    brand = CharFilter(field_name='brand__name', lookup_expr='iexact')
    category = CharFilter(field_name='category__name', lookup_expr='iexact')
    discount = NumberFilter(field_name='discount', lookup_expr='gte')

    class Meta:
        model = Product
        fields = {}

My categories queryset response looks like this

{
   "name" : "electronics"
   "parent" : None,
   "products" : []
   "children" : [
       "name" : "cameras"
       "parent" : "electronics",
       "products" : []
       "children" : [
            "name": "DSLR Cameras",
            "parent" : "cameras",
            "products": [ "name": "Cannon EOS 80D DSLR Camera" ]
       ]
   ]
}

When i send query param with category=dslr cameras, i’m able to get the products associated with this category, but if i send a parent category name like category=electronics or category=cameras, I’d want to deep search the Category model to show products if the children also have these products. How can i achieve this?

>Solution :

Try this out:

class ProductFilter(FilterSet):
    brand = CharFilter(field_name='brand__name', lookup_expr='iexact')
    category = CharFilter(method='filter_category_name')
    discount = NumberFilter(field_name='discount', lookup_expr='gte')

    class Meta:
        model = Product
        fields = {}

    def filter_category_name(self, queryset, name, value):
        return queryset.filter(category__in=Category.objects.filter(name__iexact=value).get_descendants(include_self=True))

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading