2010-04-06 139 views
14

我想創建一個表單,其中包含來自兩個單獨模型的字段以及其他一些常規(非模型)字段。該表單將創建每個模型的一個實例。我不想認爲我可以使用內聯formset,因爲我不想包含這兩個模型的所有字段。從模型字段獲取Django表單字段

我想創建表單字段,而不用硬編碼模型字段的類型。

我知道我可以使用model_field.formfield()從模型字段獲取表單字段。但是,我怎樣才能獲得特定的模型領域?

我的第一個解決方案:

def get_fields(model_class): 
    fields = {} 
    for f in model_class._meta.fields: 
     fields[f.name] = f 

class MyForm(forms.Form): 
    foo_name = get_fields(Foo)['name'].formfield() 
    bar_name = get_fields(Bar)['name'].formfield() 
    other_field = ... 

是否存在的get_fields已經等同?這是一個壞主意嗎?依靠模型_meta屬性我不舒服。或者,我是否會以完全錯誤的方式進行討論?

+0

您的解決方案聽起來很合理的,我,本書雖然,我不明白爲什麼你不想硬編碼的2場;也許你動態地獲得模型。 – 2010-04-06 11:30:13

+0

我想避免硬編碼表單域的類型,以防我改變相應模型域的類型。不確定你想要動態獲取模型的意義......? – harto 2010-04-06 13:00:10

回答

14

你也可以看看django.forms.models.fields_for_model。 這應該給你一個字段的字典,然後你可以添加表格的字段

+0

沒有注意到該方法,謝謝。這是我正在尋找的答案,但也許凱西斯塔克的建議更合適。 – harto 2010-04-07 00:11:10

11

你不應該自己構建字段,除非你想要一些特殊的行爲。

這應該就像使用兩個ModelForm s和一個額外的Form一樣在一個<form>標籤內,在您的模板中使用一個提交按鈕。

class Model1Form(forms.ModelForm): 
    class Meta: 
     model = Model1 
     fields = ('fields', 'you', 'want') 

class Model2Form(forms.ModelForm): 
    class Meta: 
     model = Model2 
     fields = ('fields', 'you', 'want') 

class ExtraFieldsForm(forms.Form): 
    extra_field = form.TextField() # or whatever field you're looking for 

在views.py:

form1 = Model1Form(request.POST or None) 
form2 = Model2Form(request.POST or None) 
form3 = ExtraFieldsForm(request.POST or None) 

if form1.is_valid() and form2.is_valid() and form3.is_valid(): 
    form1.save() 
    form2.save() 
    form3.save() 

    ...do other stuff like a redirect... 

,並在模板:

<form method="POST" action="">{% csrf_token %} 
    <fieldset> 
     {{ form1|as_uni_form }} 
     {{ form2|as_uni_form }} 
     {{ form3|as_uni_form }} 
     <div class="form_block"> 
      <input type="submit" value="Save both models"/> 
     </div> 
    </fieldset> 
</form> 

我已經習慣了使用Django的單向

在forms.py

窗體,但是你可以渲染表單域,只要你喜歡。祝你網站好運。

+0

我沒有想過在一個'

'元素中使用多個'Form'對象。感謝您的建議 - 我今晚會嘗試一下。 – harto 2010-04-07 00:09:59

+0

很酷。我希望這個對你有用。我以前看過它,但沒有經過測試。你可能需要玩視圖邏輯來獲得你想要的。 – 2010-04-07 03:20:49

2

另一種解決方案可以是創建一個聚合具體模型形式的'超級'形式。該表單支持表單通常提供的方法,並將其轉發給所有子表單。有些會很簡單,其他很複雜。該方法的一大優點是,表單之外的代碼不會受到影響(客戶端驗證代碼等)。這個概念並不是真正的革命性的,但我想事後添加會很複雜。 保羅

4

現在documented API有用於從模型類獲取模型字段:

my_model_field = MyModel._meta.get_field('my_model_field_name') 

雖然這不是正式文件,直到Django的1.8,這應該與早期的Django版本工作了。

一旦你有了這個,你可以得到表單域,像這樣:

form_field = my_model_field.formfield()