2010-08-20 20 views
13
üzerinde

KeyError atarak Formumuzu göndermeye çalıştığımda 'parola' için bir KeyError alıyorum.Django clean yöntemi, POE

iz:

Request Method: POST 
Request URL: http://localhost:8000/register/ 
Django Version: 1.2.1 
Python Version: 2.7.0 
Installed Applications: 
['django.contrib.auth', 
'django.contrib.contenttypes', 
'django.contrib.sessions', 
'djangoproject1.authentication'] 
Installed Middleware: 
('django.middleware.common.CommonMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 
'django.contrib.auth.middleware.AuthenticationMiddleware') 


Traceback: 
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response 
    100.      response = callback(request, *callback_args, **callback_kwargs) 
File "C:\Users\jec23\My Java Projects\djangoproject1\src\djangoproject1\authentication\views.py" in register 
    20.   if rf.is_valid() and pf.is_valid(): 
File "C:\Python27\lib\site-packages\django\forms\forms.py" in is_valid 
    121.   return self.is_bound and not bool(self.errors) 
File "C:\Python27\lib\site-packages\django\forms\forms.py" in _get_errors 
    112.    self.full_clean() 
File "C:\Python27\lib\site-packages\django\forms\forms.py" in full_clean 
    268.   self._clean_form() 
File "C:\Python27\lib\site-packages\django\forms\forms.py" in _clean_form 
    296.    self.cleaned_data = self.clean() 
File "C:\Users\jec23\My Java Projects\djangoproject1\src\djangoproject1\authentication\forms.py" in clean 
    16.   if self.cleaned_data['cpassword']!=self.cleaned_data['password']: 

Exception Type: KeyError at /register/ 
Exception Value: 'password' 

görünümler:

def register(request): 
    if request.method == 'POST': 
     rf = forms.RegisterForm(request.POST) 
     pf = forms.ProfileForm(request.POST) 
     if rf.is_valid() and pf.is_valid(): 
      newuser = User(username=rf.cleaned_data['username'],email=rf.cleaned_data['email']) 
      newuser.set_password(rf.cleaned_data['password']) 
      newuser.save() 
      profile = pf.save(commit=False) 
      profile.user = newuser 
      profile.save() 
      return HttpResponseRedirect("/register-success/") 
     else: 
      return render_to_response("authentication/index.html", {'form1': rf, 'form2':pf}) 
    else: 
     return main(request) 

formlar:

class RegisterForm(forms.Form): 
    username = forms.CharField(min_length=6,max_length=15) 
    password = forms.CharField(min_length=6,max_length=15,widget = forms.PasswordInput()) 
    cpassword = forms.CharField(label='Confirm Password',widget = forms.PasswordInput()) 
    email = forms.EmailField(label='E-mail Address') 

    def clean(self): 
     if self.cleaned_data['cpassword']!=self.cleaned_data['password']: 
      raise forms.ValidationError("Passwords don't match") 
     return self.cleaned_data 

class ProfileForm(forms.ModelForm): 
    phonenumber = forms.CharField(label='Phone Number') 

    class Meta: 
     model = UserProfile 
     exclude = ('user') 
+0

Bu formu kullanan kodu gönderir misiniz? –

+0

dahil görünüm kodu – JPC

+0

Şablon kodunu da gönderebilir misiniz? –

cevap

10

Aha! Gördüğünüz doğrulama hata mesajı aslında bir doğrulama hatası mesajı değildir. Açıklamama izin ver. Eğer as_p kullanarak modeli formu örneği hale zaman, şu şekilde her alanı oluşturur:

<p><label ...>fieldname</label> <input ... name="fieldname" /> HELP TEXT IF ANY</p> 

Eğer alanın sağ tarafına görüyoruz dize Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters yardım metni başka bir şey değildir. Bu yardım metni model tanımından alınmıştır - bunu django/contrib/auth/models.py adresini ziyaret ederek ve User sınıfının tanımını denetleyerek doğrulayabilirsiniz.

username alanını geçersiz kıldığınızda, herhangi bir yardım metnini atlıyorsunuz. Doğal olarak "hata" ortadan kalkar.

Bu teoriyi doğrulamak için main yönteminizde aşağıdakileri yapın. Kullanıcı bir ya password ve cpassword her iki tedarik vermediğinde

def main(request): 
    uf = forms.UserForm() 
    upf = forms.UserProfileForm() 
    print "User form is bound:%s errors:%s" % (uf.is_bound, uf.errors) 
    return render_to_response("authentication/index.html", {'form1': uf, 'form2':upf}) 

Güncelleme

if self.cleaned_data['cpassword']!=self.cleaned_data['password']: 

Bu çizgi sorun neden olabilir. Örneğin, Django kabuğundan bu deneyin:

>>> data = dict(username = 'admin', cpassword = 'foo', email='[email protected]') 
>>> f = RegisterForm(data) 
>>> f.is_bound 
True 
>>> f.is_valid() 

Traceback (most recent call last): 
    ... 
    File "<pyshell#2>", line 8, in clean 
    if self.cleaned_data['cpassword']!=self.cleaned_data['password']: 
KeyError: 'password' 
hem değerler karşılaştırarak önce mevcut olduğundan emin olmak için Formun clean yöntemini değiştirme

. Böyle bir şey:

def clean(self): 
    password = self.cleaned_data.get('password', None) 
    cpassword = self.cleaned_data.get('cpassword', None) 
    if password and cpassword and (password == cpassword): 
     return self.cleaned_data 
    else: 
     raise forms.ValidationError("Passwords don't match") 
+0

Ah geçersiz kılmaya çalışmadığımda aldığım doğrulama hata mesajı bu!Bu bir tonluk hissi veriyor. Bunu asla anlayamazdım. Kullanıcı için ModelForm ile biraz sinirlendim çünkü alanları yeniden tanımlamak zorunda kaldım ve hala bir sebepten dolayı bu KeyError'u alıyorum. Düzenli bir form kullanarak bitirdim ve sadece Kullanıcıyı yarattım. – JPC

+0

Yardım metnini geçersiz kılmadan gitmek mümkün mü? – JPC

+0

@JPC: Formun '__init__' yöntemini geçersiz kılabilir ve 'self.fields [' username ']' i ayarlayabilirsiniz. Help_text = None'. Biraz çılgın IMHO. Alternatif olarak, yardım metnini yok saydığınız formu görüntülemek için başka bir yöntem kullanabilirsiniz. –

11

kendi deneyimlerinden, bunu sen = Gerçek gerektiği gibi size formda clean() yöntemini geçersiz zaman, işaretlenmişlerdir dahi birden fazla alanda bazı doğrulama yapmak istiyorsanız, bulundu Doğrulamak istediğiniz alanlar gönderilirken doldurulmazsa ve bunları cleaned_data["field_name"] olarak kabul etmeye çalışırsanız, kodunuz KeyError ile patlayabilir. Bundan kaçınmak için, get() sözlük yöntemiyle clean_data alanındaki alana erişin ve Yok mu, yoksa varsayılan değeri mi kontrol edin. Bunun doğal sonucu olarak:

my_field = cleaned_data.get("field_name") # This is safe and it will work! :) 
my_filed = cleaned_data["field_name"] # This will crash when the field was not filled! :(

Bu başkası, çünkü bu saçma şey zamanının büyük miktarda kayıp umut olur!

+0

Bu cevap olmalı – Gnoliz

İlgili konular