如何使用Django通用视图过滤表?

时间:2014-08-12 04:36:23

标签: django django-class-based-views django-tables2 django-filter

我正在尝试使用最常见/标准/推荐的Django 1.6方法创建一个带分页,排序和过滤的表视图。这似乎是基于通用类的视图和django-tables2。我找到了至少两个不同的添加过滤示例,一个使用django-filters and crispy-forms,另一个使用django_filters,但都没有包含完整的工作示例。当我遵循任何一种方法时,我都会陷入困境中。使用Nicolas Kuttler的脆弱方法,我有:

models.py

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

tables.py

import django_tables2 as dt2
from .models import Author

class AuthorTable(dt2.Table):
    class Meta:
        model = Author

如果我理解正确的话,PagedFilteredTableView是一个泛型类,然后我将其作为子类,而不是另一个例子,其中FilteredSingleTableView,我认为应该被理解为类似,如果Author是表,AuthorFilteredSingleTableView

views.py

from .tables import AuthorTable
from .models import Author
from django_tables2 import SingleTableView

class PagedFilteredTableView(SingleTableView):
    """
    Generic class from http://kuttler.eu/post/using-django-tables2-filters-crispy-forms-together/
    which should probably be in a utility file
    """
    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_table(self, **kwargs):
        table = super(PagedFilteredTableView, self).get_table()
        RequestConfig(self.request, paginate={'page': self.kwargs['page'],
                            "per_page": self.paginate_by}).configure(table)
        return table

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

class AuthorTableView(PagedFilteredTableView):
    model = Author
    table_class = AuthorTable
    paginate_by = 30
    filter_class = AuthorFilter
    formhelper_class = AuthorFilterFormHelper

除了模板之外,来自source和manage.py的所有示例代码都抱怨AuthorFilter没有被定义,所以我想这会进入...也许filters.py?< / p>

filters.py

import django_filters as df
from .models import Author

class AuthorFilter(df.FilterSet):
    class Meta:
        model = Author

然后,回到views.pyfrom .filters import AuthorFilter

现在AuthorFilterFormHelper尚未定义,并且我不清楚我应该明确定义的内容(如何?),如行{{1}所暗示的那样或者,如果实际上应该以某种方式自动完成,如formhelper_class = FooFilterFormHelper暗示的那样。我们仍然没有得到urls.py或模板。请帮助填写空白,或指示更好的路径,以便将过滤添加到基于通用类的视图。

2 个答案:

答案 0 :(得分:9)

经过反复试验和Nicolas Kuttler的一些建议,我得以his example工作。我宰了他的一些例子,但这看起来似乎接近Django所需的最少量的代码,有一个基于类的基于列表的查看页面,包括排序,过滤(以及搜索)和分页,我不知道#39;认为它违反了(太m)任何Django编码实践。以下是所有必需的代码:

models.py (问题没有变化)

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

问题中 tables.py 略有变化:

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 (问题没有变化)

import django_filters as df
from .models import Author

class AuthorFilter(df.FilterSet):
    class Meta:
        model = Author

<强> forms.py 即可。我无法弄清楚如何/从何处获取django_filters中的表单提交按钮以及其他所有内容,因此此代码禁止表单包装器标签来自crispy,然后我们在模板中提供HTML,这可能是这是最重要的部分。

from django import forms
from .models import Author
from crispy_forms.helper import FormHelper

class AuthorListFormHelper(FormHelper):
    model = Author
    form_tag = False

我将views.py中的帮助函数移动到一个单独的文件中,并且必须删除分页代码以防止出错(尽管分页仍然有效)。所以,

<强> 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

而不是问题中的 views.py ,这个 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

这个模板:

author_list.html (该名称未在任何地方明确指定,因为我认为该模型隐含在该视图中)

{% 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 %}

并且,为了完整性, urls.py 中的一行:

    ...
    url(r'^$', views.AuthorTableList.as_view(), name='author_table'),
    ...

您必须按照说明安装和配置软件包django-tables2,django-filters和crispy-forms。绊倒我的一件事是我在第一次尝试时错过了我在 settings.py 中需要的东西:

CRISPY_TEMPLATE_PACK = 'bootstrap'

所有这些都适用于Django 1.6。

答案 1 :(得分:2)

您的回答对我有帮助,因此我编辑了您的代码以包含来自crispy-forms的提交按钮

  

forms.py。我无法弄清楚如何/从何处获取django_filters中的表单提交按钮以及其他所有内容,因此这段代码会从crispy中抑制表单包装器标签,然后我们在模板中提供HTML,这可能是kludgiest部分内容。

forms.py(已更新)

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(已更新)

{% 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 %}