因为这个错误让我在一周内被咬了两次,所以写下这篇答案。
来到这个问题上,它对我解决问题没有任何帮助。
这段代码的问题在于你将一个对象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():
form.save()
return HttpResponseRedirect('/members-contact/')
请看箭头。如果您将其与用户详细信息表单的__init__定义进行比较,您会发现init不期望该请求的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__定义为__init__(self, *args, **kwargs)
上面的动态表单初始化是一个很好的例子。
看起来django将传入的变量在这种情况下视为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是由超类方法创建的。如果你没有这样做,你会遇到另一个属性错误,即没有名为fields的字段。
编辑
Django提供了一个方便的方法get_form_kwargs,用于向继承自django.views.generic.edit.ModelFormMixin的表单视图(例如FormView)的init添加属性。
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')
super().__init__(*args, **kwargs)
self.fields['some_field'].queryset = SomeModel.objects.filter(user=user)
obj.user
设置为UserProfile
的实例? - Joseph Victor ZammitOneToOneField
对象来引用User
对象。我正在尝试强制设置它。 - Alex Stewart