2008-09-16 25 views
7

我有一個Web報表,它使用Django表單(新表單)來控制用於生成報表的查詢(開始日期,結束日期等)。我遇到的問題是頁面應該使用表單的初始值(未綁定),但我無法訪問cleared_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

如果添加這個方法將你的窗體類:

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')) 
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']) 

我還沒有嘗試過,雖然這一點;有人可以證實這一點嗎?我認爲這比創建一個新的方法更好,因爲這種方法不需要其他代碼(可能不是你寫的)來了解你的新'魔術'訪問器。

+0

是的,但是然後默認值沒有用表單定義(就像字段聲明中的initial = value一樣)。如果你在多個地方使用表格,那麼你將不得不重複你的默認值。 – davidavr 2008-09-16 19:18:24

1

沒有限制意味着沒有與形式相關的數據(無論是初始還是稍後提供),因此驗證可能會失敗。正如其他答案(以及您自己的結論)中所述,您必須提供初始值並檢查綁定數據和初始值。

表單的用例是表單處理驗證,因此您在訪問cleaned_data之前必須先驗證一些數據。