2010-03-09 41 views
30

這些框架正在展示與我想要的相反的行爲。Django formsets:首先要求?

我的觀點是建立這樣的:

def post(request): # TODO: handle vehicle formset 
    VehicleFormSetFactory = formset_factory(VehicleForm, extra=1) 
    if request.POST: 
     vehicles_formset = VehicleFormSetFactory(request.POST) 
    else: 
     vehicles_formset = VehicleFormSetFactory() 

而且我的模板看起來像這樣:

<div id="vehicle_forms"> 
     {{ vehicles_formset.management_form }} 
     {% for form in vehicles_formset.forms %} 
      <h4>Vehicle {{forloop.counter}}</h4> 
      <table> 
       {% include "form.html" %} 
      </table> 
     {% endfor %} 
    </div> 

這樣,它最初只產生1的形式,像我想要的。但我希望這種形式是必需的!

當我動態地添加空格與JavaScript和vehicles_formset.empty_form所有這些額外的形式是必需的,我不想要的。

從文檔:

的表單集是足夠聰明,忽略不改變額外的形式。

這是第一種形式表現行爲(不是我想要的),但並不是多餘的形式呈現(我想)的行爲。

是否有一些屬性我可以更改爲至少使一個窗體所需?

+0

@ MPEN雖然我遲到了黨,我不知道如何去一個稍微不同的問題我在這裏面臨我的問題(https://stackoverflow.com/questions/44159559/need-to-have-a-required-and-optional-fields-in-django-formset) – dungu 2017-05-25 08:40:58

+0

@kedric你問錯誤的人。自從我發佈這個問題後不久我就沒有使用過Django。 – mpen 2017-05-25 18:20:34

+0

ooh,好的兄弟感謝您的回覆 – dungu 2017-05-25 18:44:44

回答

65

找到一個更好的解決方案:

class RequiredFormSet(BaseFormSet): 
    def __init__(self, *args, **kwargs): 
     super(RequiredFormSet, self).__init__(*args, **kwargs) 
     for form in self.forms: 
      form.empty_permitted = False 

然後創建表單集是這樣的:

MyFormSet = formset_factory(MyForm, formset=RequiredFormSet) 

我真的不知道這是爲什麼不開始與一個選項.. 。 但是無所謂。我的人生只花了幾個小時才弄清楚。

這將使所有需要的形式。您可以通過將self.forms[0].empty_permitted設置爲False來製作所需的第一個。

+1

這是Django最煩人的部分之一的解決方案,這是爲什麼這不是文檔的一部分,這是莫名其妙的 – YPCrumble 2014-03-03 06:24:59

+0

由於某種原因,當我試圖將一個特定的表單設置爲empty_permitted時,我得到一個keyError。例如「form [0] .empty_permitted = False」給出錯誤。 – 2014-06-18 15:24:40

+0

@Zorpix應該是'self.forms [0]'我想,假設你至少有一種形式。 – mpen 2014-06-18 17:40:44

1

哦,我想我明白了。試試這個:

from django.forms.formsets import BaseFormSet, formset_factory 
class OneExtraRequiredFormSet(BaseFormSet): 
    def initial_form_count(self): 
     return max(super(OneExtraRequiredFormSet,self).initial_form_count() - 1,0) 

VehicleFormSetFactory = formset_factory(VehicleForm, formset=OneExtraRequiredFormSet, extra=1) 

低於==原來的答覆

當你說「至少讓需要一個形式」,我想你的意思是「做只需要一個額外的形式,無論有多少已通過JavaScript添加「。

您需要在頁面上隱藏輸入,其中包含通過javascript添加的表單數量,然後使用該數字減1作爲要作爲extra屬性傳遞給您的formset構造函數的值。

+0

不完全...現在忽略JavaScript,只顯示一個表單(extra = 1,沒有初始數據)。 *一個*表格不是必需的 - 我希望它是。任何通過JS添加的表單都不應該被要求。 – mpen 2010-03-09 04:34:10

+0

我的編輯幫助嗎? – Wogan 2010-03-09 04:53:26

+0

這有一些奇怪的行爲。當我將表單留空並提交時,它會添加另一個表單,並將錯誤添加到新表單中,但仍不會驗證第一個表單。 – mpen 2010-03-09 05:00:43

9

那麼......這使得需要的第一個表單。

class RequiredFormSet(BaseFormSet): 
    def clean(self): 
     if any(self.errors): 
      return 
     if not self.forms[0].has_changed(): 
      raise forms.ValidationError('Please add at least one vehicle.') 

唯一的「問題」是,如果有0形式,那麼clean方法似乎並沒有得到所謂的好,所以我不知道如何檢查是否有0真的..這個應該是永遠不會發生的(除了我的JS有一個bug,允許你刪除所有的表格)。

+1

如果您使用此表單編輯現有的一組對象,則將始終強制更新第一個對象。這僅適用於創建,而不是更新。 – 2014-09-09 03:48:26

+0

@Daniel Palm,你有解決方案嗎?我也有同樣的問題。 – 2017-05-15 10:46:03