我有一个django-tables2表,正在使用django-filter进行过滤。我已根据this great answer中的选项D 实施了一个方案。
但是,我使用django-crispy-forms和bootstrap3进行表单渲染。这很有用,直到我想要应用RangeFilter,它会吐出两个字段(最小和最大字段)。
我得到的输出是
我想手动控制每个字段,以便我可以单独使用PrependedAppendedText。
有什么想法吗?
views.py
from crispy_forms.bootstrap import PrependedAppendedText, FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Button
from django_tables2 import SingleTableView
from aids.filters import AidFilter
import os
class FilteredSingleTableView(SingleTableView):
filter_class = None
def get_table_data(self):
self.filter = AidFilter(
self.request.GET,
queryset=super(FilteredSingleTableView, self).get_table_data(),
)
self.filter.helper = FormHelper()
self.filter.helper.form_id = 'id_filterForm'
self.filter.helper.form_class = 'form-inline'
self.filter.helper.form_method = 'get'
self.filter.helper.form_tag = True
self.filter.helper.field_template = os.path.join('bootstrap3', 'layout', 'inline_field.html')
self.filter.helper.layout = Layout(
'name',
PrependedAppendedText('price', '$', 'min', ),
# Fieldset(
# 'Filter by price',
# PrependedAppendedText('price_0', '$', 'min', id='id_price_0'),
# PrependedAppendedText('price_1', '$', 'max', id='id_price_1'),
# ),
'maint',
'post',
'supplier',
FormActions(
Submit('submit_filter', 'Filter', css_class='btn-primary'),
Button('clear', 'Clear', css_class='btn-sm')
)
)
return self.filter
def get_context_data(self, **kwargs):
context = super(FilteredSingleTableView, self).get_context_data(**kwargs)
context['filter'] = self.filter
return context
filters.py
import django_filters
from aids.models import Aid
class AidFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_type='contains')
price = django_filters.RangeFilter()
class Meta:
model = Aid
fields = ['name', 'price', 'maint', 'post', 'supplier']
view_table.html
{% extends 'base.html' %}
{% block title %}{{ title }}{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{{ STATIC_URL }}django_tables2/themes/paleblue/css/screen.css" />
{% endblock %}
{% load render_table from django_tables2 %}
{% load crispy_forms_tags %}
{% block heading %}
{{ title }}
{% endblock %}
{% block content %}
{% crispy filter.form filter.helper %}
{% render_table table %}
{% endblock %}
urls.py
from django.conf.urls import patterns, include, url
from django.conf.urls.static import static
from django.contrib import admin
from aids.filters import AidFilter
from aids.models import Aid
from aids.tables import AidTable
from sadb import settings
from aids.views import FilteredSingleTableView
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^aid_form/', 'aids.views.aid_form'),
url(r'^supplier_form/', 'aids.views.supplier_form'),
url(r'^view_aids/', 'aids.views.view_aids'),
url(
r'^$', FilteredSingleTableView.as_view(
model=Aid,
table_class=AidTable,
template_name='view_table.html',
filter_class=AidFilter
), name='filtered_view'
),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
答案 0 :(得分:1)
在覆盖DateRangeFilter
之后我遇到了类似的问题,并通过修改窗口小部件输出来绕过它,并使用form-inline
类和def format_output()
中的修改位对其进行div包装在小部件类的末尾。
https://docs.google.com/file/d/0BwIBq4D09D0RaDZGTWhCWnJaZU0的屏幕截图(声誉已经让我发布了图片!)
我的完整代码如下(最初取自https://groups.google.com/d/msg/django-filter/lbi_B4zYq4M/37s63u0WrncJ)
class DateRangeWidget(forms.MultiWidget):
def __init__(self, attrs=None):
attrs_from = {'class': 'date-from'}
attrs_to = {'class': 'date-to'}
if attrs:
attrs_from.update(attrs)
attrs_to.update(attrs)
widgets = (forms.TextInput(attrs=attrs_from), forms.TextInput(attrs=attrs_to))
super(DateRangeWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return [value.start, value.stop]
return [None, None]
def format_output(self, rendered_widgets):
return '<div class="date-range form-inline">' + ' - '.join(rendered_widgets) + '</div>'
class DateRangeField(forms.MultiValueField):
widget = DateRangeWidget
def __init__(self, *args, **kwargs):
fields = (
forms.DateField(),
forms.DateField(),
)
super(DateRangeField, self).__init__(fields, *args, **kwargs)
def compress(self, data_list):
if data_list:
return slice(*data_list)
return None
class DateRangeFilter(Filter):
field_class = DateRangeField
def filter(self, qs, value):
date_start = datetime.datetime.combine(value.start, datetime.time(0, 0, 0))
date_stop = datetime.datetime.combine(value.stop, datetime.time(23, 59, 59))
if value:
lookup = '%s__range' % self.name
return qs.filter(**{lookup: (date_start, date_stop)})
return qs