写这个答案是因为我在一周内被这个错误咬了两次。
来到这个问题并没有帮助我解决问题。
此代码的问题在于您已将 request.user 对象传递到 UserDetailsForm 的 init 函数中。和你的定义init不处理 request.user 发生的情况。
userprofile = UserProfile.objects.get(user=request.user)
if request.method == 'POST':
====>form = UserDetailsForm(request.user, request.POST, request.FILES)
if form.is_valid(): # it dies here
form.save()
return HttpResponseRedirect('/members-contact/')
参见箭头。如果将其与 __init__of 用户详细信息表单的定义进行比较。您可以看到 init 并不期望该 request.user
class UserDetailsForm(ModelForm):
class Meta:
model = UserProfile
fields = ['mobile_phone']
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
return super(UserDetailsForm, self).__init__(*args, **kwargs)
请注意,编写 init 来传递对象是有正当理由的。
def __init__(self, some_object, *args, **kwargs):
super(SomeFormClass, self).__init__(self, *args, **kwargs)
self.fields['some_field'].queryset = SomeModel.objects.filter(some_field = some_object)
另请注意,modelform 的 __init__ 的默认 def 具有 __init__(self, *args, **kwargs)
上面的动态表单初始化就是一个很好的例子。
在这种情况下,django 似乎将 request.user 中传入的变量视为 some_field ,并尝试调用“UserModel”没有的名为 get 的方法。如果您检查堆栈跟踪,您会注意到。下面的堆栈跟踪是一个模拟示例。
Traceback (most recent call last):
File "/home/user/.local/lib/python3.5/site-packages/django/core/handlers/exception.py", line 39, in inner
response = get_response(request)
return render(request, self.template_name, context)
File "/home/user/.local/lib/python3.5/site- packages/django/shortcuts.py", line 30, in render
content = loader.render_to_string(template_name, context, request, using=using)
---
---
---
packages/django/forms/forms.py", line 297, in non_field_errors
return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield'))
File "/home/user/.local/lib/python3.5/site-packages/django/forms/forms.py", line 161, in errors
self.full_clean()
---
---
---
self._clean_fields()
File "/home/user/.local/lib/python3.5/site-packages/django/forms/forms.py", line 382, in _clean_fields
===>value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))<====
File "/home/sodara/.local/lib/python3.5/site-packages/django/forms/widgets.py", line 238, in value_from_datadict
====> return data.get(name) <====
AttributeError: 'SomeObject' object has no attribute 'get'
data.get 是方法调用结果的返回值 field.widget.value_from_data_dict ...
如果您注意到,SomeObject 被视为此处的数据,其 get 方法正在被调用。
要回答这个问题,要么定义 init 来处理 request.user
def __init__(self, user, *args, **kwargs):
super(YourFormClass, self).__init__(*args, **kwargs):
self.fields["some_field"].some_attr = user
或者在没有 request.user 的情况下调用表单
`form = YourFormClass(request.POST, request.FILES)`
如果您决定选择选项一。你必须记住在调用 self.fields 之前先调用 super。因为 self.fields 是由 super 方法创建的。如果不这样做,您将遇到另一个属性错误“没有名为字段的字段”。
Edit
Django提供了一个方便的方法get_form_kwargs
用于向继承自的表单视图的 init 添加属性django.views.generic.edit.ModelFormMixin
例如FormView
.
class MyFormView(FormView):
form_class = MyModelFormClass
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
class MyModelFormClass(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user') # Important to do this
# If you dont, calling super will fail because the init does
# not expect, user among the fields.
super().__init__(*args, **kwargs)
self.fields['some_field'].queryset = SomeModel.objects.filter(user=user)