在课堂上添加** kwarg

时间:2009-06-12 15:19:15

标签: python django

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']

我想在此表单中添加一个选项,允许我创建一个这样的表单:

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

但我不知何故需要在该类中“添加”该关键字参数,以便识别它。他们现在的方式,我只是得到这个错误:

__init__() got an unexpected keyword argument 'bases_queryset'

2 个答案:

答案 0 :(得分:11)

那是因为你正在将kwargs解包给超级构造函数。 在调用super之前尝试将其放入:

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

但这不是一个理想的解决方案......

答案 1 :(得分:11)

如@Keeper所示,您不得将“new”关键字参数传递给超类。在你打电话给超级__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变得更加混乱,啊...... - )