2013-03-28 73 views
0

可以說我有這樣的形式:如何動態修改django widget參數?

class ChangeParentCIForm(ModelForm): 
    class Meta: 
     model = CINodeInventory 
     fields = ('parent',) 
     widgets = {'parent': AutocompleteWidget('inventory.uuid'),} 

的問題是,在我的情況下,AutocompleteWidget內容必須是上下文不僅與「父」字段的值,而且與用戶會話信息(我的一個數據庫版本號由另一個頁面上的用戶)

要做到這一點,我做了這樣的事情到基於類的視圖選擇:

class CompanyManageChangeParentCIView(CompanySelectedMixin,CIContextMixin,CompanyViewCIMixin,UpdateView):  
    template_name = 'inventory/browse_change_parent_ci.html' 
    context_object_name = 'ci' 
    form_class = ChangeParentCIForm 

    def get_form(self,form_class): 
     form = super(CompanyManageChangeParentCIView,self).get_form(form_class) 
     form.base_fields['parent'].widget.url_params={'version':self.request.session['use_version']} 
     return form 

當然我修改AutocompleteWidget代碼照顧這個'url_params'額外參數。

它的工作原理,但由於它在修改初始時間創建控件對於同樣以初始時間產生的場這段代碼不能在我看來,非常漂亮。 與anothers也就是說,如果你創建了2種形式的情況下,它指向相同的字段和窗口小部件,所以,如果我這樣做:

def get_form(self,form_class): 
    form1 = super(CompanyManageChangeParentCIView,self).get_form(form_class) 
    form2 = super(CompanyManageChangeParentCIView,self).get_form(form_class) 
    form1.base_fields['parent'].widget.url_params="val1" 
    form2.base_fields['parent'].widget.url_params="val2" 
    print id(form1),id(form1.base_fields['parent'].widget) 
    print id(form2),id(form2.base_fields['parent'].widget) 

可以看到Form 1和Form是不同的實例,但它們指向相同的小部件(如果打印它們的id,則是相同的字段)。因此,對於我來說,如果我將form1和form2顯示到同一個模板中,我將顯示2個窗口小部件「AutocompleteWidget」,但都是用最新修改自定義的,即url_parms =「val2」

即使如果我顯示一個窗體,在我看來,非常危險,如果2個線程正在執行相同的代碼,併爲同一個小部件使用2個不同的「url_params」值,會發生什麼?

因此,這裏是我的問題:如何自定義Django的部件與上下文信息的渲染,不僅是在其相關領域的價值?

回答

2

因爲你正在改變form.base_fields,這是由類的所有實例共享。不要這樣做,請更改form.fields,這是特定於實例的。

作爲一個風格問題,我更願意做這個形式本身的__init__方法,並通過URL PARAM作爲一種形式kwarg - 看起來像您可以覆蓋視圖的get_form_kwargs方法來做到這一點,那麼你根本不需要改變get_form