I am trying to create a table view with pagination, sorting, and filtering, using the most common/standard/recommended approach for Django 1.6. This seems to be Generic Cla
Your answer help me, so i edited your code to include the submit button from crispy-forms
forms.py. I couldn't figure out how/where to get the form submit button out of django_filters in combination with everything else, so this code suppresses the form wrapper tags from crispy, and then we provide that HTML in the template, which is probably the kludgiest part of this.
forms.py (UPDATED)
from django import forms
from .models import Author
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, ButtonHolder, Submit
class AuthorListFormHelper(FormHelper):
model = Author
form_tag = False
# Adding a Filter Button
layout = Layout('name', ButtonHolder(
Submit('submit', 'Filter', css_class='button white right')
))
author-list.html (UPDATED)
{% extends "base.html" %}
{% load render_table from django_tables2 %}
{% load crispy_forms_tags %}
{% block content %}
{% render_table table %}
<hr/>
<form action="" method="get">
{% crispy filter.form filter.form.helper %}
</form>
{% endblock content %}
With trial and error and some suggestions from Nicolas Kuttler, I was able to get his example working. I butchered a little bit of his example but this does seem to be close to the least amount of code necessary in Django to have a generic class-based list view page with sorting, filtering (and thus search), and pagination, and I don't think it violates (too m)any Django coding practices. Here is all of the code required:
models.py (no changes from the question)
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
And a slight change to the tables.py in the question:
import django_tables2 as dt2
from .models import Author
class AuthorTable(dt2.Table):
class Meta:
model = Author
attrs = {"class": "paleblue"}
per_page = 30
filters.py (no changes from the question)
import django_filters as df
from .models import Author
class AuthorFilter(df.FilterSet):
class Meta:
model = Author
forms.py. I couldn't figure out how/where to get the form submit button out of django_filters in combination with everything else, so this code suppresses the form wrapper tags from crispy, and then we provide that HTML in the template, which is probably the kludgiest part of this.
from django import forms
from .models import Author
from crispy_forms.helper import FormHelper
class AuthorListFormHelper(FormHelper):
model = Author
form_tag = False
I moved the helper function out of views.py to a separate file and had to remove the pagination code to prevent an error (though pagination still works). So,
utils.py
from django_tables2 import SingleTableView
from django_tables2.config import RequestConfig
class PagedFilteredTableView(SingleTableView):
filter_class = None
formhelper_class = None
context_filter_name = 'filter'
def get_queryset(self, **kwargs):
qs = super(PagedFilteredTableView, self).get_queryset()
self.filter = self.filter_class(self.request.GET, queryset=qs)
self.filter.form.helper = self.formhelper_class()
return self.filter.qs
def get_context_data(self, **kwargs):
context = super(PagedFilteredTableView, self).get_context_data()
context[self.context_filter_name] = self.filter
return context
Instead of the views.py in the question, this views.py:
from .models import Author
from .tables import AuthorTable
from .filters import AuthorListFilter
from .forms import AuthorListFormHelper
from utils import PagedFilteredTableView
class AuthorList(PagedFilteredTableView):
model = Author
table_class = AuthorTable
filter_class = AuthorListFilter
formhelper_class = AuthorListFormHelper
And this template:
author_list.html (the name is not explicitly specified anywhere because it's implied by the model in the view, I think)
{% extends "base.html" %}
{% load render_table from django_tables2 %}
{% load crispy_forms_tags %}
{% block content %}
{% render_table table %}
<hr/>
<form action="" method="get">
{% crispy filter.form filter.form.helper %}
<input type="submit" value="Filter"/>
</form>
{% endblock content %}
And, for completeness, a line in urls.py:
...
url(r'^$', views.AuthorTableList.as_view(), name='author_table'),
...
And you must have the packages django-tables2, django-filters, and crispy-forms installed and configured as per their instructions. The one thing that tripped me up was that I somehow, on the first attempt, missed that I needed this in settings.py:
CRISPY_TEMPLATE_PACK = 'bootstrap'
All of this is for Django 1.6.