10

我有一个网络报告,它使用 Django 表单(新表单)来控制用于生成报告的查询(开始日期、结束日期......)。我遇到的问题是页面应该使用表单的初始值(未绑定)工作,但我无法访问 clean_data 字段,除非我调用is_valid(). 但is_valid()总是在未绑定的表单上失败。

似乎 Django 的表单是为编辑数据的用例而设计的,因此未绑定的表单除了显示 HTML 之外并没有真正的用处。

例如,如果我有:

if request.method == 'GET':
    form = MyForm()
else:
    form = MyForm(request.method.POST)

if form.is_valid():
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])

is_valid() 如果这是一个 GET 将失败(因为它是未绑定的),如果我这样做:

if request.method == 'GET':
    form = MyForm()
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
else:
    form = MyForm(request.method.POST)
    if form.is_valid():
       do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])

第一次调用 do_query 会触发 form.cleaned_data 上的异常,该字段不是有效字段,因为is_valid()尚未调用。看来我必须做类似的事情:

if request.method == 'GET':
    form = MyForm()
    do_query(form['start_date'].field.initial, form['end_date'].field.initial)
else:
    form = MyForm(request.method.POST)
    if form.is_valid():
       do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])

也就是说,没有用于在绑定表单和未绑定表单之间检索表单值的通用接口。

有没有人看到更清洁的方法来做到这一点?

4

3 回答 3

7

如果将此方法添加到表单类中:

def get_cleaned_or_initial(self, fieldname):
        if hasattr(self, 'cleaned_data'):
            return self.cleaned_data.get(fieldname)
        else:
            return self[fieldname].field.initial

然后,您可以将代码重写为:

if request.method == 'GET':
    form = MyForm()
else:
    form = MyForm(request.method.POST)
    form.is_valid()

do_query(form.get_cleaned_or_initial('start_date'), form.get_cleaned_or_initial('end_date'))
于 2008-09-16T19:18:57.910 回答
2

未绑定意味着没有与表单关联的数据(初始或稍后提供),因此验证可能会失败。如其他答案(以及您自己的结论)中所述,您必须提供初始值并检查绑定数据和初始值。

表单的用例是表单处理验证,因此在访问cleaned_data.

于 2008-09-17T09:02:07.463 回答
0

您可以将初始值字典传递给您的表单:

if request.method == "GET":
    # calculate my_start_date and my_end_date here...
    form = MyForm( { 'start_date': my_start_date, 'end_date': my_end_date} )
...

请参阅官方表单 API 文档,他们在其中演示了这一点。

编辑:根据其他用户的回答,也许这是最干净的解决方案:

if request.method == "GET":
    form = MyForm()
    form['start_date'] = form['start_date'].field.initial
    form['end_date'] = form['end_date'].field.initial
else:
    form = MyForm(request.method.POST)
if form.is_valid():
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])

不过,我还没有尝试过;有人可以确认这行得通吗?我认为这比创建一个新方法要好,因为这种方法不需要其他代码(可能不是您编写的)来了解您的新“魔术”访问器。

于 2008-09-16T19:07:39.513 回答