写这个答案是因为我在一周内被这个错误咬了两次。来到这个问题,它没有帮助我找出问题。这段代码的问题是您将 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 并试图调用一个名为 get 的方法,而 'UserModel' 没有该方法。如果您检查堆栈跟踪,您会注意到。下面的堆栈跟踪是一个模拟示例。
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 方法创建的。如果你不这样做,你会遇到另一个属性错误,没有名为字段的字段。
编辑
Django 提供了一种方便的方法get_form_kwargs
,可以将属性添加到继承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)