What's wrong with my django model field?

I am trying to make a PhoneField that converts a value to a standard value.

In this case, I want to use this clean method.

def clean(self):
    phone = self.cleaned_data.get('phone')

    # Is it already standardized ?
    if phone.startswith('+'):
      mo = re.search(r'^\+\d{2,3}\.\d{9,11}$', phone)

      if not mo:
        raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
      else:
        return phone

    # If not, it must be a french number.
    phone = re.sub("\D", "", phone) # Suppression des caractères séparateurs

    mo = re.search(r'^\d{10}$', phone) # Numéro à 10 chiffres
    if not mo:
        raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
    else:
        phone = mo.group()[-9:]

    return u'+33.%s' % phone

      

If I use it in a form, it works well. But I would like to use it as a form field.

I tried to do this:

EMPTY_VALUES = (None, '')

class PhoneInput (forms.TextInput):
    def render(self, name, value, attrs=None):
        if value not in EMPTY_VALUES:
            value = phone_render(value)
        else:
            value = None

        return super(PhoneInput, self).render(name, value, attrs)

class PhoneField(models.CharField):
    widget = PhoneInput

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 16
        super(PhoneField, self).__init__(*args, **kwargs)

    def get_internal_type(self):
        return "CharField"

    def clean(self, value):
        phone = super(PhoneField, self).clean(value)

        # Le numéro contient-il un indicatif ?
        if phone.startswith('+'):
          mo = re.search(r'^\+\d{2,3}\.\d{9,11}$', phone)

          if not mo:
            raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
          else:
            return phone

        # Pas d'indicatif : on est en France par défaut
        phone = re.sub("\D", "", phone) # Suppression des caractères séparateurs

        mo = re.search(r'^\d{10}$', phone) # Numéro à 10 chiffres
        if not mo:
            raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
        else:
            phone = mo.group()[-9:]

        return u'+33.%s' % phone

      

But the pure method is never called. Can you help me?

+2


source to share


2 answers


You are mixing model fields and form fields.

You must first define the form fields and then the corresponding model. Fields should be prompted to use these form fields for a sample form.

See the documentation for specifying the-form-fields-for-model.

Basically you need to define a method called formfield on the model field



def formfield(self, **kwargs):
    # This is a fairly standard way to set up some defaults
    # while letting the caller override them.
    defaults = {'form_class': MyFormField}
    defaults.update(kwargs)
    return super(HandField, self).formfield(**defaults)

      

The field you created above has a clean method which is a requirement for the form field and not the model field

So now you have to define the form field (the one you defined, excluding the extension from forms.CharField

, not models.CharField

), and then define the model field according to the definitions of the model fields definition and include the method as above.

Alternatively and simplistically, you can simply select the form field, and in the model form, override the default form field for that particular module. (Altho 'in this case, no validation is performed if no data is entered from this model)

+6


source


This is how I fixed it using helpGuru :)

 class PhoneFormField(forms.CharField):
     widget = PhoneInput

     def clean(self, value):
         phone = super(PhoneFormField, self).clean(value)

         # Le numéro contient-il un indicatif ?
         if phone.startswith('+'):
           mo = re.search(r'^\+\d{2,3}\.\d{9,11}$', phone)

           if not mo:
             raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
           else:
             return phone

         # Pas d'indicatif : on est en France par défaut
         phone = re.sub("\D", "", phone) # Suppression des caractères séparateurs

         mo = re.search(r'^\d{10}$', phone) # Numéro à 10 chiffres
         if not mo:
             raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
         else:
             phone = mo.group()[-9:]

         return u'+33.%s' % phone

 class PhoneField(models.CharField):
     def __init__(self, *args, **kwargs):
         kwargs['max_length'] = 16
         super(PhoneField, self).__init__(*args, **kwargs)

     def get_internal_type(self):
         return "CharField"

     def formfield(self, form_class=PhoneFormField, **kwargs):
         return super(PhoneField, self).formfield(form_class=form_class, **kwargs)

      



Thank you for your help.

+1


source







All Articles