Kermit
Kermit

Reputation: 6012

Django DRY functions in forms

In my forms.py I have to setup and then clean a lot of similar variables.

class FormOne(forms.Form):
    email_field = forms.EmailField(
        required=True,
        max_length=70,
        label=mark_safe("""<i>Enter email address</i>"""))

    # other fields

    def clean_email_field(self):
        return data

class FormTwo(forms.Form):
    email_field = forms.EmailField(
        required=True,
        max_length=70,
        label=mark_safe("""<i>Enter email address</i>"""))

    # other fields

    def clean_email_field(self):
        return data

In my views.py I can successfully define a function at the bottom of the file and reference it in the code above. But if I try to put something like this at the bottom of the file:

def clean_email_field(form_data):
    # rest of function

then I get the error:

***ERROR*** clean_email_field undefined

Is it because forms are classes, not defs?

Upvotes: 2

Views: 451

Answers (1)

Ralf
Ralf

Reputation: 16505

If you want to include additional validation to your email field, then you could maybe write a custom validator and then include it in your form field. For example:

from django import forms
from django.core.exceptions import ValidationError

def validate_contains_something(value):
    if 'something' not in value:
        raise ValidationError('no 'something' found')

class FormTwo(forms.Form):
    email_field = forms.EmailField(
        required=True,
        max_length=70,
        label=mark_safe("""<i>Enter email address</i>"""),
        validators=[
            validate_contains_something,
        ])

You could even write your custom field with your custom validators as the default (as seen in this example in the docs):

class CustomEmailField(forms.EmailField):
    def __init__(self, *args, **kwargs):
        super().__init__(
            *args,
            required=True,
            max_length=70,
            label=mark_safe("""<i>Enter email address</i>"""),
            validators=[
                validate_contains_something,
            ],
            **kwargs)

class CustomEmailField2(forms.EmailField):
    def __init__(self, *args, **kwargs):
        kwargs.setdefault('required', True)
        kwargs.setdefault('max_length', 70)
        kwargs.setdefault('label', mark_safe("""<i>Enter email address</i>"""))
        kwargs.setdefault('validators', [validate_contains_something, ])
        super().__init__(*args, **kwargs)

This approach could be an easier way to write your validation logic only once.

Upvotes: 1

Related Questions