2013-03-13 61 views
4

我的Django應用程序使用Django Suit作爲主題管理Django應用程序的工具。的事情之一西裝能做的就是追加和預先準備的元素,形成像小部件:在Django中動態修改表單部件

class PropertyForm(ModelForm): 
    class Meta: 
     model = Property 
     widgets = { 
      'amount': EnclosedInput(prepend = "GBP"), 
     } 

的效果是:

enter image description here

雖然這是一個很好的功能,如果我會比較有用可以增加它動態等(僞代碼):

'amount': EnclosedInput(prepend = my_model_instance.currency) 

我試圖重寫形式的init像這樣:

class PropertyForm(ModelForm): 

    def __init__(self, *args, **kwargs): 
     inst = kwargs["instance"] 
     self._meta.widgets["amount"] = EnclosedInput(prepend = inst.currency) 
     super(PropertyForm, self).__init__(*args, **kwargs) 

奇怪的是,當我把一個斷點在初始化方法僅適用。看起來有一些時間問題。

所以我的問題是什麼將是最好的方式(如果一個可用)來實現這個?

+0

你需要的是從多個取其值小部件實例字段。一種方法是使用'MultiValueField'和'MultiWidget'。如果這太難以工作,我可以闡述一個答案。 – 2013-03-13 11:29:23

+0

我不太確定這是要走的路。當我查看EnclosedInput(Django Suit的一部分)的代碼時,這個小部件只是標準Django TextInput的擴展,他們所做的唯一事情就是將一個帶有CSS類的添加到該小部件的HTML輸出中。我真的很困惑的事實,我的方法不工作沒有斷點和調試器停止... – Roger 2013-03-13 12:22:15

+0

我的意思是,你基本上想要一個包含兩個不同表單域的值的小部件。我認爲這是一種比黑客入侵窗體構造器更可重用的解決方案。至於調試器,也許它強制評估一些懶惰的對象? – 2013-03-13 12:29:06

回答

8

的問題是:

self._meta.widgets["amount"] = EnclosedInput(prepend = inst.currency) 

原來_meta被緩存。當我改變上述行(這也一個更好的解決方案,_meta可能是私人):

self.fields['amount'].widget = EnclosedInput(prepend = inst.currency) 

...它完美的作品

1

一個簡單的辦法是每次配置表單類,你需要它:

def make_property_form(currency): 
    class PropertyForm(forms.Form): 
     # ... 
     widgets = { 
      'amount': EnclosedInput(prepend=currency), 
     } 
    return PropertyForm 

def view_that_uses_my_form(request): 
    # ... 
    form_class = make_property_form(model.currency) 
    form = form_class(the_usual_form_initialization) 
+0

表單在管理中配置form = PropertyForm,所以這將意味着我需要將這些方法添加到PropertyAdmin類?我還需要重寫實際創建窗體的admin方法(可能是您的答案中的view_that_uses_my_form()方法... – Roger 2013-03-13 11:21:16

+0

不,這會使我的方法在您的案例中變得毫無用處,它只會在您明確構建新的表單實例在每次使用(如果你只在你自己的視圖函數中使用表單),但我不會惹惱這個管理代碼。 – 2013-03-13 11:24:22