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 aTypeErroris thrown:In the example above, the superclass is
django_filters.BooleanFilterrespectivelydjango_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_typenever changes after initialization, it can already be set in__init__().Here's a working example of the code above, where
Projectis 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: