Search code examples
pythondjangodatatablesdjango-filterdjango-tables2

Usage of Django-Filter on large tables along with DataTables2


I am using Django-Tables2 with following code to load the data on to data tables.

sales_data = SalesTable(sale.objects.all().order_by('-time'))
RequestConfig(request,paginate={'per_page': 50}).configure(sales_data)

My Sales table has 1.4 million rows and yet, the above method of RequestConfig on (django_tables2.Table) is very fast with pagination etc.

Now, I want to have a column filtering on the table and using django-filter for the same. It is taking too long time, consuming whole memory. Is there a way, I can get the filtering as speed as normal table loading?

views.py

class FilteredSingleTableView(tables.SingleTableView):
      filter_class = None

      def get_table_data(self):
         queryset_data = super(FilteredSingleTableView, self).get_table_data()
         self.filter = self.filter_class(self.request.GET, queryset = queryset_data)
         return self.filter

      def get_context_data(self, **kwargs):
         context = super(FilteredSingleTableView, self).get_context_data(**kwargs)
         context['filter'] = self.filter
         return context 


class SalesFilteredSingleTableView(FilteredSingleTableView):
      model = sale
      table_class = sales.tables.SaleFilteredTable
      filter_class = sales.filters.SaleFilter

urls.py

url(r'^filtertest$', sales_views.SalesFilteredSingleTableView.as_view() , name='salesfilterview')

filters.py

import django_filters

import sales.models

class SaleFilter(django_filters.FilterSet):
    class Meta:
        model = sales.models.sale

tables.py

import django_tables2 as tables
from sales.models import sale

class SaleFilteredTable(tables.Table):
    class Meta:
        model = sale
        attrs = {"class": "paleblue"}
        per_page = 50

Thanks in advance!


Solution

  • In CBV, instead of filter, filter.qs has to be passed. In the previous case, entire table is loaded to memory and hence loading time is more and browser crashes happening.

    With this modification, both empty filter & filterform query sets are loaded with LIMIT Query.

    views.py

    class FilteredSingleTableView(tables.SingleTableView):
    filter_class = None
    
    def get_table_data(self):
        queryset_data = super(FilteredSingleTableView, self).get_table_data()
        self.filter = self.filter_class(self.request.GET, queryset = queryset_data)
        return self.filter.qs
    
    def get_context_data(self, **kwargs):
        context = super(FilteredSingleTableView, self).get_context_data(**kwargs)
        context['filter'] = self.filter
        return context 
    
    class SalesFilteredSingleTableView(FilteredSingleTableView):
        model = sale
        table_class = SalesFilteredTable
        template_name = 'sales/sale_list.html'
        filter_class = sales.filters.SaleFilter
    

    Reference

    https://github.com/carltongibson/django-filter/issues/442