I want to use django-table2 with django-filter. I done what django-table2 document said but form of django-filter didn't display in my template.
These are my codes:
# Views.py
from django_filters.views import FilterView
import django_filters
from django_tables2 import SingleTableView
class MYFilter(django_filters.FilterSet):
class Meta:
model = MyModel
fields = ['field1', 'field2' ]
class MyView(SingleTableView, FilterView):
model = MyModel
table_class = MyTable
template_name = 'my_template.html'
filterset_class = MYFilter
# tables.py
import django_tables2 as tables
class MyTable(tables.Table):
class Meta:
model = MyModel
fields = ("field1", "field2",)
# my_template.html
{% load render_table from django_tables2 %}
{% if filter %}
<form method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
{% endif %}
{% if table %}
<div class="table-responsive">
{% render_table table %}
</div>
{% endif %}
The table render correctly, but the form didn't render. What's wrong with my code?
The method resolution order (MRO) will put the filter view that low that it has no impact, indeed:
>>> MyView.__mro__
(<class 'MyView'>,
<class 'django_tables2.views.SingleTableView'>,
<class 'django_tables2.views.SingleTableMixin'>,
<class 'django_tables2.views.TableMixinBase'>,
<class 'django.views.generic.list.ListView'>,
<class 'django_filters.views.FilterView'>,
<class 'django.views.generic.list.MultipleObjectTemplateResponseMixin'>,
<class 'django.views.generic.base.TemplateResponseMixin'>,
<class 'django.views.generic.list.BaseListView'>,
<class 'django_filters.views.BaseFilterView'>,
<class 'django_filters.views.FilterMixin'>,
<class 'django.views.generic.list.MultipleObjectMixin'>,
<class 'django.views.generic.base.ContextMixin'>,
<class 'django.views.generic.base.View'>,
<class 'object'>)
This is important since the BaseFilterView
will override the get
method, but since the BaseListView
appears first in the MRO, it will not have any impact. If we swap the parents, so:
class MyView(FilterView, SingleTableView):
# …
the mro is:
>>> MyView.__mro__
(<class 'MyView'>,
<class 'django_filters.views.FilterView'>,
<class 'django_tables2.views.SingleTableView'>,
<class 'django_tables2.views.SingleTableMixin'>,
<class 'django_tables2.views.TableMixinBase'>,
<class 'django.views.generic.list.ListView'>,
<class 'django.views.generic.list.MultipleObjectTemplateResponseMixin'>,
<class 'django.views.generic.base.TemplateResponseMixin'>,
<class 'django_filters.views.BaseFilterView'>,
<class 'django_filters.views.FilterMixin'>,
<class 'django.views.generic.list.BaseListView'>,
<class 'django.views.generic.list.MultipleObjectMixin'>,
<class 'django.views.generic.base.ContextMixin'>,
<class 'django.views.generic.base.View'>,
<class 'object'>)
and thus the get
logic of the BaseFilterView
will be used.