2016-04-28 97 views
3

當Django的模型形式的工作,我經常做這樣的事情:在Django模型每個窗體的設置實例FORMSET

def my_view(request): 
    new_entry = MyModel(name='a') 
    form = MyModelForm(instance=new_entry) 
    ... 

我想要做一個modelformset類似的東西。像這樣的東西將是理想的:

def my_view(request): 
    MyFormSet = modelformset_factory(MyModel, form=MyModelForm) 
    new_entries = [MyModel(name='a'), MyModel(name='b')] 
    formset = MyFormSet(instances=new_entries) # off course this does not work 
    ... 

由於項目尚未存儲在數據庫中,我不能使用查詢集來設置實例。如果我想使用初始,我必須聲明表單中的字段,這是不理想的,似乎有點哈克。

任何建議如何在modelformset中設置每個模型的實例?

回答

2

好吧,我想我找到了一個解決方案。

class FormSetWithInstances(BaseFormSet): 
    def __init__(self, *args, **kwargs): 
     self.instances = kwargs.pop('instances') 
     super(FormSetWithInstances, self).__init__(*args, **kwargs) 

    def get_form_kwargs(self, index): 
     form_kwargs = super(FormSetWithInstances, self).get_form_kwargs(index) 
     if index < len(self.instances): 
      form_kwargs['instance'] = self.instances[index] 
     return form_kwargs 

使用此modelformsets或inlinemodelformsets時要小心,因爲queryset會覆蓋您設置的實例。

1

我還沒有意識到一個簡單的方法來傳遞實例列表,因爲你正在嘗試做。以下是根據您的使用情況可能有效的幾個選項。

您可以provide initial data爲模型formset。這應該是一個字典列表,而不是模型實例:

initial = [{'name': 'a'}, {'name': 'b'}] 
formset = MyFormSet(
    queryset=MyModel.objects.none(), 
    initial=initial, 
) 

請注意,我已將查詢集設置爲空的查詢集。如果你沒有這樣做,那麼formset將顯示現有的實例,並且初始數據將用於新的實例。

如果您不希望包含在表單中的字段的初始值,那麼您可以在[保存表單集]時設置這些值。

instances = formset.save(commit=False) 
names = ['a', 'b'] 
for instance, name in zip(instances, names): 
    instance.name = name 
    instance.save() 
+0

我考慮過這種方法,但是我相信我必須在表單中聲明該字段。我不希望用戶編輯這個字段,所以我不得不將它添加到我的模板中作爲隱藏字段(因爲表單會期望它)。這是正確的方法嗎?仍然看起來不像我用普通模型表格那樣乾淨。 – Johan

+0

好吧,現在我明白你爲什麼不想在窗體上聲明這些字段。我同意隱藏的字段並不理想 - 用戶仍然可以更改他們提交的值。 – Alasdair

+0

我實際上在自定義驗證期間需要這些初始值。我應該使用正常的formset嗎?或者創建我自己的自定義表單?這樣,我仍然可以使用初始而無需將其聲明爲表單字段。 – Johan

相關問題