我有一个网页报告,它使用Django表单(新表单)来控制用于生成报告的查询的字段(开始日期,结束日期......)。我遇到的问题是页面应该使用表单的初始值(未绑定),但我无法访问cleaning_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'])
如果这是一个GET(因为它是未绑定的),is_valid()将失败,如果我这样做:
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'])
也就是说,没有一个公共接口可以检索绑定表单和未绑定表单之间的表单值。
有没有人看到更清洁的方法呢?
答案 0 :(得分:4)
如果将此方法添加到表单类:
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'))
答案 1 :(得分:2)
未绑定表示没有与表单关联的数据(初始或稍后提供),因此验证可能会失败。正如其他答案(以及您自己的结论)中所述,您必须提供初始值并检查绑定数据和初始值。
表单的用例是表单处理和验证,因此在访问cleaned_data
之前,您必须拥有一些要验证的数据。
答案 2 :(得分: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} )
...
请参阅official forms API documentation,他们会证明这一点。
修改:根据其他用户的回答,也许这是最干净的解决方案:
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'])
我没试过这个;有人可以证实这有效吗?我认为这比创建一个新方法更好,因为这种方法不需要其他代码(可能不是你编写的)来了解你的新“魔术”访问器。