2

I have a model which relates to many models, like this:

class Father:
   son = # Foreign key to Son model

class Son:
   @property
   def son_daughters:
      if ... :
         obj = TypeA.objects.get(...)
      elif ... :
         obj = TypeB.objects.get(...)
      else:
         obj = TypeC.objects.get(...)

      return obj

I would like to get Father data from daughter name or type. I have this filter class where I need to send two query set parameters related to daughter in order to get daughter ids and apply it as a filter to Father. This is my filter class:

class FatherFilter(django_filters.rest_framework.FilterSet):
   def daughter(self, method_name, args, **kwargs):

        print(method_name, args, kwargs)
        ...

   daughter_id = django_filters.NumberFilter(method=daughter)

But when I call this endpoint I just get one query parameter and not all.

Is there a way to get the query parameters inside this method instead of just one?

Thanks in advance.

5
  • This doesn't appear to have anything to do with DRF. django-filters is a completely separate package. Commented Jan 27, 2017 at 19:23
  • Django Rest implements django-filters as a package to use Django Filter classes, please verify it: django-rest-framework.org/api-guide/filtering/… Commented Jan 27, 2017 at 19:30
  • For history/context, django-filter is an entirely separate package. However, DRF used to provide a 'filter backend' that allowed you to easily integrate django-filter with DRF. This filter backend has since been moved to the django_filters.rest_framework sub-package. The issue that you're running into here isn't directly related to DRF. Commented Jan 31, 2017 at 10:36
  • It's not entirely clear what it is that you're trying to do here. Could you provide an example URL or query string as well as the queryset that should be produced by the filterset? As to your question, you can access self.data directly, although I don't recommend this since you'd be bypassing validation. Commented Jan 31, 2017 at 10:57
  • Thanks, @Sherpa. Sorry I wasn't clear enough, I posted this code as example of the desired result, but the true code relies in many models and views that might be more complex for understanding the final results. I found the way to achieve this, tough it might not be the best way to do it but it works now. I'll post the answer below. Commented Jan 31, 2017 at 17:30

1 Answer 1

2

In order to achieve this, I found that Django Rest Framework has a class that extends from django_filters. This class is called BaseFilterBackend and can be used to extend the default backend for filtering any request. So what I did was adding a class extended from BaseFilterBackend like this:

from rest_framework import filters

class FatherFilterBackend(filters.BaseFilterBackend):
   def filter_queryset(self, request, queryset, view):
      daughter_id = request.query_params.get("daughter_id", None)
      daughter_name = request.query_params.get("daughter_name", None)

      if daughter_id and daughter_name:
         kwargs = {
            daughter_name: daughter_id
         }
         queryset = queryset.filter(**kwargs)

      return queryset

This filter will apply before others, so even if you are using a FilterSet class, you will not lose the filters from your BaseFilterBackend. The problem with this solution is that relies in rest_framework.filters package, a filter that its not related to django_filters.

This might not be the best way to achieve this, so if you have better ideas please add them to help others with a similar problem.

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

1 Comment

Thanks for this. the DRF docs dont mention where the import comes from!

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.