在 Django 中处理过滤器表单以及其他 get 参数



我有一个 django 表单,其中包含 2 个必填字段和一些可选字段,用于过滤视图中呈现的数据。

除了过滤器表单的参数外,此视图还使用了一些GET参数,我正在从类似form = MyFilterForm(request.GET or None)初始化我的过滤器 [请参阅下面代码中的 (1(]。

我发现当我的视图首次加载并且没有GET参数时,这工作正常,因为request.GET是假的,因此表单不会被绑定(因此我们使用必填字段的初始值(。如果使用过滤器表单,则request.GET填充表单参数,并且一切再次正常运行。但是,如果我的其他GET参数之一(即用于对结果数据表进行排序的参数(在没有使用过滤器表单的情况下被传递,那么request.GET是真实的,但没有任何与表单对应的参数,因此表单被绑定并且错误无效,因为我的必填字段没有被赋予值。

这里应该发生的事情是数据表应该被排序,表单应该继续使用初始("默认"(值,就像第一次加载它一样。

这有点难以解释,并且使用某些代码可能会更清楚......

我已经用谷歌搜索了大量内容,因为这感觉像是其他人也必须遇到的问题,但没有任何运气找到任何东西。

我正在使用 django-tables2 为用户呈现表中的数据,但这个问题更多地围绕表单,关于表格,您唯一需要了解的是它允许用户通过单击表格标题对表格中显示的数据进行排序 - 然后向请求添加一个 GET 参数,其中包含按 I.E?sort=start_date排序的列。

class MyFilterForm(forms.Form):
date_from = DateTimeField(required=True)
date_to = DateTimeField(required=True)
user = ModelChoiceField(required=False, queryset=User.objects.all())
def __init__(self, *args, **kwargs):
super(MyFilterForm, self).__init__(*args, **kwargs)
# dates in correct timezone and at start/end of day
# initial values set in __init__ so that they aren't fixed at import time
week_start, week_end = get_start_end_week(timezone.now())
self.fields['date_from'].initial = week_start
self.fields['date_to'].initial = week_end

在我看来

import django-tables2 as tables

@login_required
def view_with_filter_form_and_table(request):
form = MyFilterForm(request.GET or None)  # (1) The form gets bound when the table is sorted here as request.GET is truthy
if form.is_bound and form.is_valid():
date_from = self.cleaned_data['date_from']
date_to = self.cleaned_data['date_to']
else:
# use defaults if not bound or not valid
date_from = form.fields['date_from'].initial
date_to = form.fields['date_to'].initial
user = form.cleaned_data.get('user') if form.is_bound else None
query = Action.objects.all()
if date_from:
query = query.filter(date__gte=date_from)
if date_to:
query = query.filter(date__lte=date_to)
if user:
query = query.filter(user=user)
table = MyTable(query)
tables.RequestConfig(request, paginate=False).configure(table)
return render(request, 'my_form_and_table.html', {'form': form, 'table': table})

我考虑过的

在绑定到表单之前检查所有必填字段是否都在request.GET中。除了有点代码气味之外,因为我需要实例化一个未绑定的表单来迭代所有字段并检查所需的字段是否request.GET,甚至知道我是否应该实例化绑定表单。这里的问题是,如果表单被编辑并且用户将其中一个必填字段设置为空,我仍然希望显示验证错误,也就是This field is required.

我目前通过在标记为 (1( 的代码下添加以下代码来解决此问题,但如果有更干净的解决方案,我会喜欢它。

for name, field in form.fields.items():
if field.required and name not in request.GET:
form = MyFilterForm(None)  # unbound form
break

最新更新