问题
I'm making a custom user form where a user can go in to change some details. It got two errors that I cannot understand what the problem is though.
The first problem is that the form doesn't fill out the user details. And it seems to be because self
is empty when form is initialized, why?
And the second problem is that when I submit this form, it will complain about some KeyError, which I don't get either. I've pasted the code and stacktrace.
Trackback
Environment:
Request Method: POST
Request URL: http://localhost:8000/settings/
Django Version: 1.4
Python Version: 2.7.2
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'social_auth')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "c:\tools\python27\lib\site-packages\django-1.4-py2.7.egg\django\core\handlers\base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "c:\tools\python27\lib\site-packages\django-1.4-py2.7.egg\django\contrib\auth\decorators.py" in _wrapped_view
20. return view_func(request, *args, **kwargs)
File "C:\xampp\htdocs\tddd27_project\contact\views.py" in settings
47. if form.is_valid():
File "c:\tools\python27\lib\site-packages\django-1.4-py2.7.egg\django\forms\forms.py" in is_valid
124. return self.is_bound and not bool(self.errors)
File "c:\tools\python27\lib\site-packages\django-1.4-py2.7.egg\django\forms\forms.py" in _get_errors
115. self.full_clean()
File "c:\tools\python27\lib\site-packages\django-1.4-py2.7.egg\django\forms\forms.py" in full_clean
270. self._clean_fields()
File "c:\tools\python27\lib\site-packages\django-1.4-py2.7.egg\django\forms\forms.py" in _clean_fields
290. value = getattr(self, 'clean_%s' % name)()
File "c:\tools\python27\lib\site-packages\django-1.4-py2.7.egg\django\contrib\auth\forms.py" in clean_password
122. return self.initial["password"]
Exception Type: KeyError at /settings/
Exception Value: 'password'
views.py
def settings(request):
if request.method == 'POST':
form = UserProfileForm(request.POST)
if form.is_valid():
form.save()
return HttpResponse("Change success")
else:
form = UserProfileForm(instance=request.user)
return render_to_response('settings.html',{'form': form}, context_instance=RequestContext(request))
forms.py
class UserProfileForm(UserChangeForm):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name')
exclude = ('password',)
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
if self.instance and self.instance.pk:
self.fields['username'] = self.instance.username
self.fields['first_name'] = self.instance.first_name
self.fields['last_name'] = self.instance.last_name
template
{% extends "base.html" %}
{% block title %}
Settings
{% endblock title %}
{% block content %}
{{ user.username }}
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit">
</form>
{% endblock content %}
回答1:
Regarding your second problem, I also came across the same issue today, while updating from Django 1.3 to Django 1.4. I had a custom form just like you:
class UserProfileForm(UserChangeForm):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', )
I solved the problem by adding a clean_password
method like this:
class UserProfileForm(UserChangeForm):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', )
def clean_password(self):
return "" # This is a temporary fix for a django 1.4 bug
回答2:
The first problem is that the form doesn't fill out the user details. And it seems to be because self is empty when form is initialized, why?
This is initiating a new blank modelform: UserProfileForm()
or UserProfileForm(request.POST)
This is initiating a modelform bound to the user instance: UserProfileForm(instance=request.user)
or UserProfileForm(request.POST, instance=request.user)
.
If you don't fully understand this, please read the documentation about ModelForm usage.
In your view, you are instantiating new blank forms, instead of forms bound to the request.user instance. e.g. this UserProfileForm(request.POST)
should be UserProfileForm(request.POST, instance=request.user)
Then, this is absolutely not necessary:
if self.instance and self.instance.pk:
self.fields['username'] = self.instance.username
self.fields['first_name'] = self.instance.first_name
self.fields['last_name'] = self.instance.last_name
This doesn't fix the KeyError, but you should change:
exclude = ('password')
To:
exclude = ('password',)
Note that in the second case, exclude is a tuple. See this example in python shell:
In [1]: ('foo')
Out[1]: 'foo'
In [2]: ('foo',)
Out[2]: ('foo',)
As for your KeyError, well I'm really unsure. I can see the problem but I've not cracked how it's supposed to work yet. Anyhow, if password is excluded, this function should not be run anyway.
回答3:
class UserProfileForm(UserChangeForm):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', )
def clean_password(self):
return self.clean_password
This will solve the issue. Hope this helps.
来源:https://stackoverflow.com/questions/9875993/django-userchangeform-errors