2009-06-12 52 views
3
class StatusForm(ModelForm): 

    bases = forms.ModelMultipleChoiceField(
      queryset=Base.objects.all(), #this should get overwritten 
      widget=forms.SelectMultiple, 
     ) 

    class Meta: 
     model = HiringStatus 
     exclude = ('company', 'date') 

    def __init__(self, *args, **kwargs): 
     super(StatusForm, self).__init__(*args, **kwargs) 
     if kwargs.has_key('bases_queryset'): 
      self.fields['bases'].queryset = kwargs['bases_queryset'] 

我想一個選項添加到該表單,讓我創建一個表單,像這樣:添加** kwarg一類

form = StatusForm(bases_queryset=Base.objects.filter([...]) 

但不知何故,我需要「補充」這個關鍵詞所以它會被認可。他們的方法是現在,我剛剛得到這個錯誤:

__init__() got an unexpected keyword argument 'bases_queryset'

回答

11

那是因爲你拆包kwargs的超級構造函數。 嘗試調用超之前把這個:

if kwargs.has_key('bases_queryset'): 
    bases_queryset = kwargs['bases_queryset'] 
    del kwargs['bases_queryset'] 

,但它不是一個理想的解決方案...

+8

更好的方法很簡單: bases_queryset = kwargs.pop(「bases_queryset」,無) 這將刪除字典中的關鍵,給你它的價值,如果它存在那裏,也初始化爲None當鑰匙不在那裏。 – 2009-06-14 10:17:52

11

由於@Keeper表示,你不能傳遞你的「新」的關鍵字參數的超類。最可能做的,你叫超級的__init__前:

bqs = kwargs.pop('bases_queryset', None) 

__init__調用後,檢查if bqs is not None:而不是使用has_key(和使用bqs代替kwargs['bases_queryset'],當然)。

一個有趣的替代方法是做一個「選擇性呼叫」高階函數。這是一個有點亂,如果你有兩個位置和命名參數(這就是總是有點亂來元程序周圍;-),因此爲了簡化說明採用的功能要選擇調用只有「正常」的命名參數(即沒有**k)。現在:

import inspect 

def selective_call(func, **kwargs): 
    names, _, _, _ = inspect.getargspec(func) 
    usable_kwargs = dict((k,kwargs[k]) for k in names if k in kwargs) 
    return func(**usable_kwargs) 

使用這種方法,在你__init__,而不是調用超級的__init__直接,你會打電話來 selective_call(super_init, **kwargs),讓這個高階函數做必要的「修剪」。 (當然,你需要使其梅西耶同時處理位置,並命名爲ARGS,不錯啊...... - - !)