Mar*_*row 21 django django-forms
在使用构造函数overriden实例化Django表单时出现以下错误:
__init__() got multiple values for keyword argument 'collection_type'
Run Code Online (Sandbox Code Playgroud)
的__init__()功能(下面示出)被完全按照写入这个但# code代替我的逻辑.请注意,我基本上重写了表单(这是一个ModelForm)构造函数.
def __init__(self, collection_type, user=None, parent=None, *args, **kwargs):
# code
super(self.__class__, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
创建错误的调用如下所示:
form = CreateCollectionForm(
request.POST,
collection_type=collection_type,
parent=parent,
user=request.user
)
Run Code Online (Sandbox Code Playgroud)
我看不出错误弹出的原因.
编辑:这是构造函数的完整代码
def __init__(self, collection_type, user=None, parent=None, *args, **kwargs):
self.collection_type = collection_type
if self.collection_type == 'library':
self.user = user
elif self.collection_type == 'bookshelf' or self.collection_type == 'series':
self.parent = parent
else:
raise AssertionError, 'collection_type must be "library", "bookshelf" or "series"'
super(self.__class__, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
编辑:Stacktrace
Environment:
Request Method: POST
Request URL: http://localhost:8000/forms/create_bookshelf/hello
Django Version: 1.1.1
Python Version: 2.6.1
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'libraries',
'users',
'books',
'django.contrib.admin',
'googlehooks',
'registration']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware')
Traceback:
File "/Library/Python/2.6/site-packages/django/core/handlers/base.py" in get_response
92. response = callback(request, *callback_args, **callback_kwargs)
File "/Library/Python/2.6/site-packages/django/contrib/auth/decorators.py" in __call__
78. return self.view_func(request, *args, **kwargs)
File "/Users/marcus/Sites/marcuswhybrow.net/autolib/libraries/forms.py" in create_collection
13. form = CreateCollectionForm(request.POST, collection_type=collection_type, user=request.user)
Exception Type: TypeError at /forms/create_bookshelf/hello
Exception Value: __init__() got multiple values for keyword argument 'collection_type'
Run Code Online (Sandbox Code Playgroud)
Dan*_*man 43
您将collection_type参数作为关键字参数传递,因为您collection_type=collection_type在调用表单构造函数时特别说.因此Python将其包含在kwargs字典中 - 但是因为您还在该函数的定义中将其声明为位置参数,所以它会尝试将其传递两次,从而导致错误.
但是,你要做的事永远不会奏效.你不能有user=None, parent=None 以前的*args字典,因为这些都已经kwargs,和args必须kwargs之前总会来.修复它的方法是删除collection_type,user和parent的显式定义,并从函数中的kwargs中提取它们:
def __init__(self, *args, **kwargs):
collection_type = kwargs.pop('collection_type', None)
user = kwargs.pop('user', None)
parent = kwargs.pop('parent', None)
Run Code Online (Sandbox Code Playgroud)
这很简单:你传递request.POST,之后你就为collection_type设置了参数.在什么request.POST将被放?没有地方.看这个:
In [8]: class A:
...: def __init__(self, a, *args):
...: print a, args
...:
...:
In [9]: A(None, a=None)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/gruszczy/Programy/logbuilder/<ipython console> in <module>()
TypeError: __init__() got multiple values for keyword argument 'a'
Run Code Online (Sandbox Code Playgroud)
将request.POST移动到调用中的其他位置,但请记住,命名参数位于那些之后,而不是.
丹尼尔罗斯曼的解决方案是处理混合*args和**kwargs更好的,但gruszczy的解释是正确的:
您已CreateCollectionForm.__init__使用此签名定义:
def __init__(self, collection_type, user=None, parent=None, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
然后你就这样称呼它:
form = CreateCollectionForm(
request.POST,
collection_type=collection_type,
parent=parent,
user=request.user
)
Run Code Online (Sandbox Code Playgroud)
self在通话期间隐式分配.之后,Python只看到一个位置参数:request.POST,它被指定为collection_type第一个参数.然后,处理关键字参数,当Python看到另一个关键字参数名称时collection_type,它必须抛出一个TypeError.
Daniel的解决方案是一个很好的解决方案,通过删除所有命名参数,可以更轻松地处理这样的事情,并将它们传递super()给更高级别的构造函数.或者,您需要将post字典作为__init__方法的第一个形式参数,并将其传递给超类.
| 归档时间: |
|
| 查看次数: |
31109 次 |
| 最近记录: |