简体   繁体   中英

Why my Django form is not raising validation error?

Following is my form code:

class ConfirmEmailForm(forms.Form):
    email = forms.EmailField()
    subscribe = forms.IntegerField()
    code = forms.CharField(max_length=80)

    def clean_subscribe(self):
        value = bool(self.cleaned_data['subscribe'])
        self.cleaned_data['subscribe'] = value
        return value

    def clean(self):
        cleaned_data = super(ConfirmEmailForm, self).clean()
        email = cleaned_data['email']
        code = cleaned_data['code']
        user = User.objects.filter(username=email).first()
        if not user:
            raise forms.ValidationError('Email not found')
        self.cleaned_data['user'] = user
        if user.emailverification.is_key_expired():
            raise forms.ValidationError('Link expired, please regenerate')
        if not user.emailverification.key == code:
            raise forms.ValidationError('Invalid Link')
        return cleaned_data

I am using this form for a GET request. Now when I send the request without email field, I was expecting that the error will be raised at cleaned_data , however it doesn't raise any error and rather I get KeyError at next line.

Obviously it will raise an KeyError since it is absent. But my question, why the error is not being raised at super(ConfirmEmailForm, self).clean() itself.

Here is the full traceback:

Environment:


Request Method: GET
Request URL: http://localhost:8000/user/confirm/?code=g&subscribe=1

Django Version: 1.9.6
Python Version: 3.5.1
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'nightreads',
 'nightreads.posts',
 'nightreads.user_manager']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/Users/avi/.virtualenvs/nightreads/lib/python3.5/site-packages/django/core/handlers/base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "/Users/avi/.virtualenvs/nightreads/lib/python3.5/site-packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/avi/.virtualenvs/nightreads/lib/python3.5/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/Users/avi/.virtualenvs/nightreads/lib/python3.5/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/Users/avi/Documents/code/nightreads/nightreads/user_manager/views.py" in get
  54.         if form.is_valid():

File "/Users/avi/.virtualenvs/nightreads/lib/python3.5/site-packages/django/forms/forms.py" in is_valid
  161.         return self.is_bound and not self.errors

File "/Users/avi/.virtualenvs/nightreads/lib/python3.5/site-packages/django/forms/forms.py" in errors
  153.             self.full_clean()

File "/Users/avi/.virtualenvs/nightreads/lib/python3.5/site-packages/django/forms/forms.py" in full_clean
  363.         self._clean_form()

File "/Users/avi/.virtualenvs/nightreads/lib/python3.5/site-packages/django/forms/forms.py" in _clean_form
  390.             cleaned_data = self.clean()

File "/Users/avi/Documents/code/nightreads/nightreads/user_manager/forms.py" in clean
  30.         email = cleaned_data['email']

Exception Type: KeyError at /user/confirm/
Exception Value: 'email'

Why it is happening? And how do I solve this? What is the proper way to access validated and cleaned data in clean ?

If the clean method gets an error it will add it to the list of errors, it doesn't raise it.

You can find the line of code here .

        except ValidationError as e:
            self.add_error(name, e)

You could resolve it by using cleaned_data.get('email') which will return None if the value isn't found - which you can then check against.

Before doing cleaned_data['email'] check any error existing or not.

def clean(self):
    cleaned_data = super(ConfirmEmailForm, self).clean()

    if any(self.errors):
        return self.errors

    email = cleaned_data['email']
    code = cleaned_data['code']

Hope this will work for you.

I think that's because when you use the clean method Any ValidationError raised by this method will not be associated with a particular field;

Try to create a custom except for this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM