[Fixed]-How to add an initial/default value using Django Filters?


You can try overriding the __init__ method of UserFilter:

def __init__(self, *args, **kwargs):
    super(UserFilter, self).__init__(*args, **kwargs)
    self.form.initial['archive'] = False


For DRF you can try override __init__:

def __init__(self, *args, **kwargs):
    kwargs['data']._mutable = True
    if 'archive' not in kwargs['data']:
        kwargs['data']['archive'] = False
    kwargs['data']._mutable = False
    super(UserFilter, self).__init__(*args, **kwargs)

But you should read django-filter.readthedocs.io…using-initial-values-as-defaults


I had a similar problem in that I wanted to preserve the users selections even after they had navigated away from the page. I implemented my solution in the Filter View as follows…

class BucketLookupView(UserPassesTestMixin,SingleTableMixin,FilterView):
    template_name = "finance/planning-bucket-lookup.html"
    model = finance_models.SalesOrderBucket
    filterset_class = finance_filters.BucketFilter
    table_class = finance_tables.BucketTable

    def get_filterset_kwargs(self,*args):
        kwargs = super().get_filterset_kwargs(*args)
        if kwargs['data']:
            bucket_filter_data = kwargs['data']
            self.request.session['bucket_filter_data']= bucket_filter_data
            if 'bucket_filter_data' in self.request.session.keys():
        return kwargs  


Here is an approximate code snippet I used:

def list(self, request, *args, **kwargs):
    filters = QueryDict('is_archive=true', mutable=True)

You build a new QueryDict as request.GET is immutable. Not that efficient, but looks pretty to me.


Here is a remix of @IlyaPetukhov’s answer that I find easier to read:

def __init__(self, data=None, *args, **kwargs):
    if data is not None:
        data = data.copy()
        data.setdefault("archive", False)  
    super(UserFilter, self).__init__(data, *args, **kwargs)

If you’re uncomfortable with data = data.copy(), you can replace it with data._mutable = True; just know that it’s not officially supported by Django.


form.cleaned_data is using to add filters to the queryset and no initial value is set for cleaned data.
The solution could be to override form property:

def form(self) -> ModelForm:
    form = super().form
    form.data = form.data.copy()
    form.data.setdefault("archive", False)
    return form


After reading django-filter warnings, I opted to redirect if filter is not set:

from django.http import QueryDict

class EntrepriseList(LoginRequiredMixin, SingleTableMixin, FilterView):
    table_class = EntrepriseTable
    model = Entreprise
    template_name = 'stage/entreprise_list.html'
    filterset_class = EntrepriseFilter
    paginate_by = 30

    def get(self, request, *args, **kwargs):
        if request.GET:
            return super().get(request, *args, **kwargs)
            qd = QueryDict(mutable=True)
            qd['archive'] = False
            urlnext = reverse('current_page_name') # or just url from request
            urlnext += f'?{qd.urlencode()}'
            return HttpResponseRedirect(urlnext)

Leave a comment