2010-06-14 16 views
17

我想動態更新Meta.fields。是否有可能從Form構造函數中完成它?我嘗試了以下,但year不顯示在窗體生成過程中。僅顯示nametitle如何從窗體構造函數動態更新Django Form的Meta類字段?

class Author(models.Model): 
    name = ... 
    title = ... 
    year = ... 

class PartialAuthorForm(ModelForm): 
    class Meta: 
     model = Author 
     fields = ('name', 'title') 

    def __init__(self, *args, **kwargs): 
     self.Meta.fields += ('year',) 

回答

17

不,那不行。在你甚至到達__init__之前,元素被驚人地解析爲元類。

做到這一點的方法是手動添加字段self.fields:通過元類,這是之前創建的實例創建的ModelForm類時

def __init__(self, *args, **kwargs): 
    super(PartialAuthorForm, self).__init__(*args, **kwargs) 
    self.fields['year'] = forms.CharField(whatever) 
0

Meta類已經處理。做你想在__init__做的事情不會那樣工作!
例如,您可以通過字冠self.fields訪問創建的字段對象。你可以做一些像self.fields['year'] = forms.MyFormField(...)

4

答案說使用__init__可以工作,但是你失去了與模型的連接(假設你添加的字段在模型上)。相反,您可以動態地創建一個從現有表單繼承的新表單。

def my_form_factory: 
    class ModifiedAuthorForm(PartialAuthorForm): 
     class Meta(PartialAuthorForm.Meta): 
      fields = PartialAuthorForm.Meta.fields 
      if hasattr(fields, 'append'): 
       fields.append('year') 
      else: 
       fields = fields + ('year',) 
return ModifiedAuthorForm 

當然,如果你想成爲強大的你應該檢查你添加的字段是不是已經在fields,你或許應該處理exclude爲好。

14

其他人的回答都很好(特別是@BranHandley's),但有時候,最簡單的條件是刪除。顯然,這不適用於動態創建的東西,但如果您只需要選擇包含一個字段或不包含字段,則可以像這樣嘗試。

class MyModelForm(ModelForm): 
    class Meta: 
    model = MyModel 
    fields = ['normalField', 'conditionalField', ] 

    def __init__(self, *args, **kwargs): 

    super(MyModelForm, self).__init__(*args, **kwargs) 

    if condition is True: 
     del self.fields['conditionalField'] 

這樣做可能相當複雜,如上所述,但有條件地放棄它非常簡單。 =)

+0

我認爲這是最優雅的解決方案,你會不鬆從ModelForms類魔法。但是不要忘記在__init__中調用super()。 – bjunix 2014-04-16 14:28:50

+0

糟糕!更正了,謝謝! – mkoistinen 2014-07-02 23:36:58

0

通過重寫窗體的__init__方法將字段添加到模型窗體將不起作用,因爲模型窗體字段在窗體構造函數調用之前被初始化。因此,您不會從實際模型獲得任何值到表單,並且在保存調用後您的值不會保存到數據庫。

您需要使用Python的充滿美感和使用類裝飾這樣;)

def year_decorator(form_class): 
    class ModifiedForm(form_class): 
     class Meta(form_class.Meta): 
      if isinstance(form_class.Meta.model, Author): 
       fields = form_class.Meta.fields + ('year',) 
    return ModifiedForm 


@year_decorator 
class PartialAuthorForm(ModelForm): 
    class Meta: 
     model = Author 
     fields = ('name', 'title') 
相關問題