为何自定义ModelForm的__init__可接收request但super调用报TypeError
自定义ModelForm传递request参数报错原因解析
核心原理
Python方法的参数匹配规则只和当前方法的定义有关,和父类的方法参数规则无关。
1. 自定义MyModelForm.__init__可正常接收request的原因
自定义构造方法的签名为def __init__(self, *args, **kwargs):,其中**kwargs的作用就是接收所有未被显式声明的关键字参数,传入的request=request不属于该方法的显式参数,会被自动存入kwargs字典中,因此不会触发参数匹配错误。
2. 调用super().__init__抛出TypeError的原因
父类ModelForm.__init__的签名中既没有显式声明request参数,也没有定义**kwargs来接收多余的关键字参数,当把包含request键的kwargs直接传给父类构造方法时,父类方法无法识别这个未声明的参数,就会抛出__init__() got an unexpected keyword argument 'request'的异常。
正确写法
注释掉的kwargs.pop('request')就是处理这个问题的标准写法,在调用父类构造方法之前先将额外参数从kwargs中移除,保证传递给父类的参数完全匹配父类的参数声明即可:
class MyModelForm(forms.ModelForm): class Meta: model = MyModel def __init__(self, *args, **kwargs): self.request = kwargs.pop('request') super().__init__(*args, **kwargs)
简化复现示例
用极简Python代码即可复现相同逻辑:
class Parent: # 父类无request参数,也无**kwargs接收额外参数 def __init__(self, name=None): self.name = name class Child(Parent): # 子类用**kwargs接收所有额外参数 def __init__(self, *args, **kwargs): # 直接调用父类构造方法会触发参数不匹配报错 # super().__init__(*args, **kwargs) self.request = kwargs.pop('request') super().__init__(*args, **kwargs) # 实例化子类不会报错 c = Child(name="测试", request="请求对象")
内容的提问来源于stack exchange,提问作者Viktor
相关产品推荐
相关产品推荐

