0

I'm trying to override clean() method of the form to check, whether attribute IBAN is unique or not. Each user can have IBAN. For some reason, django says that form has no attribute IBAN which isn't true. As you can see it's a first attribute of the form.

Do you know what's problem?

class TranslatorRegistrationForm(forms.Form):
    IBAN = forms.CharField(max_length=40, required=True)
    first_name = forms.CharField(max_length=40, required=True)
    last_name = forms.CharField(max_length=40, required=True)
    languages = forms.ModelMultipleChoiceField(Language.objects.all(), label='Languages: ',
                                               help_text="You can choose from UNKNOWN levels, to gain level, you will be tested")

    def __init__(self,user,*args, **kwargs):
        super(TranslatorRegistrationForm, self).__init__(*args, **kwargs)
        self.user = user

    def clean(self):
        cleaned_data = super(TranslatorRegistrationForm, self).clean()
        if len(UserProfile.objects.filter(IBAN=self.IBAN).exclude(user=self.user))>0:
            raise ValidationError
        return cleaned_data

TRACEBACK:

Environment:

Request Method: POST
Request URL: http://127.0.0.1:8000/register-as-translator/

Django Version: 1.8.12
Python Version: 2.7.10
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'SolutionsForLanguagesApp',
 'crispy_forms',
 'super_inlines',
 'django_tables2',
 'language_tests',
 'smart_selects',
 'django_extensions',
 'constance',
 'constance.backends.database',
 'nested_inline')
Installed Middleware:
('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',
 'django.middleware.security.SecurityMiddleware',
 'django.middleware.locale.LocaleMiddleware')


Traceback:
File "C:\Users\Milano\PycharmProjects\FutileStudio\SolutionsForLanguages_2\venv\lib\site-packages\django\core\handlers\base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Milano\PycharmProjects\FutileStudio\SolutionsForLanguages_2\venv\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
  22.                 return view_func(request, *args, **kwargs)
File "C:\Users\Milano\PycharmProjects\FutileStudio\SolutionsForLanguages_2\SolutionsForLanguagesApp\views.py" in register_as_translator
  110.         if register_as_translator_form.is_valid():
File "C:\Users\Milano\PycharmProjects\FutileStudio\SolutionsForLanguages_2\venv\lib\site-packages\django\forms\forms.py" in is_valid
  184.         return self.is_bound and not self.errors
File "C:\Users\Milano\PycharmProjects\FutileStudio\SolutionsForLanguages_2\venv\lib\site-packages\django\forms\forms.py" in errors
  176.             self.full_clean()
File "C:\Users\Milano\PycharmProjects\FutileStudio\SolutionsForLanguages_2\venv\lib\site-packages\django\forms\forms.py" in full_clean
  393.         self._clean_form()
File "C:\Users\Milano\PycharmProjects\FutileStudio\SolutionsForLanguages_2\venv\lib\site-packages\django\forms\forms.py" in _clean_form
  417.             cleaned_data = self.clean()
File "C:\Users\Milano\PycharmProjects\FutileStudio\SolutionsForLanguages_2\SolutionsForLanguagesApp\forms.py" in clean
  116.         if len(UserProfile.objects.filter(IBAN=self.IBAN).exclude(user=self.user))>0:

Exception Type: AttributeError at /register-as-translator/
Exception Value: 'TranslatorRegistrationForm' object has no attribute 'IBAN'
3
  • Can you show me traceback? Commented Jul 21, 2016 at 9:41
  • Ok, I've added a traceback at the bottom of the question. Commented Jul 21, 2016 at 9:44
  • 1
    Once you've called super(TranslatorRegistrationForm, self).clean(), you should be able to access the value of the IBAN field in cleaned_data['IBAN']. The attribute self.IBAN is a field definition, rather than the field's value. Actually, I'll make this an answer. Commented Jul 21, 2016 at 9:46

2 Answers 2

3

Since you are validating the value of a single field iban, it would be better to define a clean_iban method instead of clean:

def clean_iban(self):
    iban = self.cleaned_data['IBAN']
    # Note using exists() is more efficient and pythonic than 'len() > 0'
    if UserProfile.objects.filter(IBAN=iban).exists():
        raise ValidationError('Invalid IBAN')
    return iban

The clean method is meant for validating fields that depend on each other. If you override clean, you can't assume that a value will be in cleaned_data.

def clean(self):
    cleaned_data = super(TranslatorRegistrationForm, self).clean()
    if 'iban' in cleaned_data:
        iban = cleaned_data['iban']
        if len(UserProfile.objects.filter(IBAN=self.IBAN).exclude(user=self.user))>0:
            raise ValidationError('Invalid IBAN')
    return cleaned_data
Sign up to request clarification or add additional context in comments.

Comments

1

Once you've called super(TranslatorRegistrationForm, self).clean(), you should be able to access the value of the IBAN field in cleaned_data['IBAN']. The attribute self.IBAN is a field definition, rather than the field's value.

4 Comments

You can't assume that 'IBAN' will be in cleaned_data. Your code should use something like if 'IBAN' in cleaned_data or iban = cleaned_data.get('IBAN'), to avoid a KeyError.
@Alasdair We have to assume that IBAN may not be in cleaned_data when overriding clean() method and don't have to assume that if we override (resp. creating) clean_IBAN() method? (According to your answer)
@Milano Yes, that's right. See the docs for clean_<field> and clean that I linked to for examples and an explanation.
Okay, I'll leave this answer unedited, since the comments don't make sense otherwise.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.