How do I filter tables with Django generic views?

后端 未结 2 1579
攒了一身酷
攒了一身酷 2020-12-14 05:03

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

相关标签:
2条回答
  • 2020-12-14 05:31

    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 %}
    
    0 讨论(0)
  • 2020-12-14 05:53

    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.

    0 讨论(0)
提交回复
热议问题