Diego Martins
Diego Martins

Reputation: 23

Modify value of a Django form field during clean() and validate again

I want to do something like this:

class UsuarioForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(UsuarioForm, self).__init__(*args, **kwargs)
        self.fields['cpf'].widget.attrs['maxlength'] = 14
        self.fields['telefone'].widget.attrs['maxlength'] = 15
        self.fields['celular'].widget.attrs['maxlength'] = 15



    nome = forms.CharField(widget=forms.TextInput(attrs={'readonly': True,
                                                         'icone': 'fa fa-font'}))

    usuario = forms.CharField(widget=forms.TextInput(attrs={'readonly': True,
                                                         'icone': 'fa fa-user'}))



    def clean(self):

        cleaned_data = self.cleaned_data

        self.data['cpf'] = re.sub("[\.-]", "", self.data['cpf'])

        clean_data_again_to_revalidate_the_field


    class Meta:
        model = Usuario

        exclude = ['codigo', 'estabelecimento', 'dono', 'data', 'estabelecimento', 'cargo', 'usuario']


        widgets = {

            'cpf': forms.TextInput(attrs={'placeholder': Text().cpf(),
                                          'icone': 'fa fa-credit-card',
                                          'id':'cpf',

                                          }),

            'telefone': forms.TextInput(attrs={'placeholder': Text().telefone(),
                                               'icone': 'fa fa-phone'.decode('utf-8'),
                                               'id': Text().telefone()}),

            'celular': forms.TextInput(attrs={'placeholder': Text().celular(),
                                              'icone': 'fa fa-mobile',
                                              'id': Text().celular()}),
        }

I want to change the field CPF to remove dots. After, I want to validate the field again. Is it possible?

Also, the self.data['cpf'] receiving the value is not possible. it is failing with: This QueryDict instance is immutable.

I created the method clean_cpf, but it is never called. I think because the cpf field do not appear in cleaned_data, since is invalid in the format I receive the data.

Also, the cpf is not in the cleaned_data. I think because is invalid. The cpf has the max length of 11, but when it come from the screen, the field has 14 characters. This is why I need to change the field and validate it again.

Upvotes: 2

Views: 1661

Answers (1)

bruno desthuilliers
bruno desthuilliers

Reputation: 77952

A q&d hack would be to fix the value in data directly in the form's __init__ (nb : untested code):

class UsuarioForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(UsuarioForm, self).__init__(*args, **kwargs)
        if self.data:
            # make the QueryDict mutable
            self.data = self.data.copy()
            # remove dots from data["cpf"]
            if "cpf" in self.data:
                self.data["cpf"] = self.data["cpf"].replace(".", "")
        # ...

But if you still get validation errors, when redisplaying the form the "cpf" field's data will be renderer without the dots.

A cleaner solution would be to use a custom "CreditCard" field instead since your cpf field seems to expected a credit card number. There are a couple third part implementations on the web, that might be used out of the box or at least provide a starting point.

As a side note: you override the default widgets in your form's Meta, then override the same field's "max_length" in the form's __init__, which is not quite DRY. You should set the maxlength directly in the Meta.widgets part.

Upvotes: 4

Related Questions