I'm using django-filter together with DRF. I have a favourite
-model, which is linked to several other models through a GenericRelation.
To filter for entries which have a favourite-flag, I've created a custom FavouriteFilter
, which I add to the respective model. I would like to query for the content_type_id
of the respective model in order to limit the results from Favourite
. However, I don't know how I can pass down the model
to the filter-method in the FavouriteFilter
.
Here's a code snippet to illustrate the issue:
class ProjectFilter(BaseFilter):
favourite_only = FavouriteFilter()
class FavouriteFilter(django_filters.BooleanFilter):
"""
A custom filter which returns a users favourites of an element
"""
def __init__(self, *args, **kwargs):
# gettext_lazy breaks the OpenAPI generation => use gettext instead
kwargs['label'] = gettext("My favourites")
super(FavouriteFilter, self).__init__(*args, **kwargs)
def filter(self, qs, value):
if value == True:
user = get_current_user()
content_type = ContentType.objects.get_for_model(<model>)
return qs.filter(pk__in=Favourite.objects
.filter(owner_id=user)
.filter(content_type_id=content_type)
.values_list('object_id', flat=True)
)
else:
return qs
In this example, the <model>
-attribute is missing. How can I pass down this information from Project
to the filter?
Keyword arguments can be passed down to the filter, but they need to be removed from the kwarg-dict before the super()-method is called. Otherwise they get passed on to the superclass, the superclass's
__init__()
-method doesn't know the keyword and aTypeError
is thrown:In the example above, the superclass is
django_filters.BooleanFilter
respectivelydjango_filters.Filter
.Using the
dict.pop()
-method, the keyword is removed from the kwargs-dictionary and at the same time we can save it for further use. Sincecontent_type
never changes after initialization, it can already be set in__init__()
.Here's a working example of the code above, where
Project
is the django-model I want to pass down to the filter:For my specific use-case, where I'm looking for the model that is using the filter, the model is available through the queryset as
qs.model
. The code-snippet looks like this: