Django, erros UserChangeForm

Eu estou fazendo um formulário de usuário personalizado onde um usuário pode entrar para alterar alguns detalhes. Ele tem dois erros que eu não consigo entender qual é o problema.

O primeiro problema é que o formulário não preenche os detalhes do usuário. E parece ser porque o self está vazio quando a forma é inicializada, por quê?

E o segundo problema é que quando eu submeto este formulário, ele irá reclamar sobre algum KeyError, que eu também não entendo. Eu colei o código e o stacktrace.

Rastrear

 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 

modelo

 {% extends "base.html" %} {% block title %} Settings {% endblock title %} {% block content %} {{ user.username }}  {% csrf_token %} {{ form.as_p }}   {% endblock content %} 

Em relação ao seu segundo problema, eu também me deparei com o mesmo problema hoje, enquanto atualizava do Django 1.3 para o Django 1.4. Eu tinha um formulário personalizado como você:

 class UserProfileForm(UserChangeForm): class Meta: model = User fields = ('username', 'first_name', 'last_name', ) 

Eu resolvi o problema adicionando um método clean_password como este:

 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 

O primeiro problema é que o formulário não preenche os detalhes do usuário. E parece ser porque o eu está vazio quando a forma é inicializada, por quê?

Isso está iniciando um novo modelform em branco: UserProfileForm() ou UserProfileForm(request.POST)

Isso está iniciando um modelform ligado à instância do usuário: UserProfileForm(instance=request.user) ou UserProfileForm(request.POST, instance=request.user) .

Se você não entender isso, leia a documentação sobre o uso do ModelForm .

Na sua opinião, você está instanciando novos formulários em branco, em vez de formulários ligados à instância request.user. por exemplo, este UserProfileForm(request.POST) deve ser UserProfileForm(request.POST, instance=request.user)

Então, isso não é absolutamente necessário:

  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 

Isso não corrige o KeyError, mas você deve alterar:

 exclude = ('password') 

Para:

 exclude = ('password',) 

Note que no segundo caso, excluir é uma tupla. Veja este exemplo no shell python:

 In [1]: ('foo') Out[1]: 'foo' In [2]: ('foo',) Out[2]: ('foo',) 

Quanto ao seu KeyError, bem, estou muito inseguro. Eu posso ver o problema, mas eu não tenho rachado como deve funcionar ainda. De qualquer forma, se a senha for excluída, esta function não deve ser executada de qualquer maneira.

 class UserProfileForm(UserChangeForm): class Meta: model = User fields = ('username', 'first_name', 'last_name', ) def clean_password(self): return self.clean_password 

Isso resolverá o problema. Espero que isto ajude.