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

Joe*_*cht 5 django django-filter django-class-based-views django-tables2

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

models.py

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)

tables.py

import django_tables2 as dt2
from .models import Author

class AuthorTable(dt2.Table):
    class Meta:
        model = Author
Run Code Online (Sandbox Code Playgroud)

如果我理解正确的话,PagedFilteredTableView是一个泛型类,然后我继承AuthorView,而不是另一个例子,其中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
Run Code Online (Sandbox Code Playgroud)

这是除了模板之外,源代码中的所有示例代码和manage.py都抱怨没有定义AuthorFilter,所以我想这可能是...也许filters.py?

filters.py

import django_filters as df
from .models import Author

class AuthorFilter(df.FilterSet):
    class Meta:
        model = Author
Run Code Online (Sandbox Code Playgroud)

而且,早在views.py,from .filters import AuthorFilter.

现在AuthorFilterFormHelper还没有定义,并且不清楚是否应该明确定义(如何?),如线所暗示的formhelper_class = FooFilterFormHelper,或者是否应该以某种方式自动完成,如暗示的那样self.filter.form.helper = self.formhelper_class().我们还没有得到urls.py或模板.请帮助填写空白,或指示更好的路径向下添加过滤到基于类的通用视图.

Joe*_*cht 9

经过反复试验和Nicolas Kuttler的一些建议,我得到了他的榜样.我宰了他的一些例子,但这看起来似乎接近Django所需的最少量的代码,有一个基于类的列表视图页面,包括排序,过滤(以及搜索)和分页,我不喜欢不认为它违反了(太m)任何Django编码实践.以下是所需的所有代码:

models.py(问题没有变化)

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)

并在问题中对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
Run Code Online (Sandbox Code Playgroud)

filters.py(问题没有变化)

import django_filters as df
from .models import Author

class AuthorFilter(df.FilterSet):
    class Meta:
        model = Author
Run Code Online (Sandbox Code Playgroud)

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

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

class AuthorListFormHelper(FormHelper):
    model = Author
    form_tag = False
Run Code Online (Sandbox Code Playgroud)

我将帮助函数从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
Run Code Online (Sandbox Code Playgroud)

而不是问题中的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
Run Code Online (Sandbox Code Playgroud)

这个模板:

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 %}
Run Code Online (Sandbox Code Playgroud)

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

    ...
    url(r'^$', views.AuthorTableList.as_view(), name='author_table'),
    ...
Run Code Online (Sandbox Code Playgroud)

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

CRISPY_TEMPLATE_PACK = 'bootstrap'
Run Code Online (Sandbox Code Playgroud)

所有这些都适用于Django 1.6.