TLT: How To Write a Custom Form Field For Django Forms

I wanted to change the way a user's field input was is stored inside of my database. My model is pretty simple, but it contains an EmailField, which isn't so simple to normalize as far as I know. That's why Django has a built-in normalize_email method in the UserManager class. I've decided to create a custom field, however, to address this issue.

The Problem

Setting unique=True inside of the EmailField I've constructed doesn't cut it because the form input won't be properly validated. If a user submits foobar@foomail.com and then submits FooBar@foomail.com, a duplication error won't be raised. That's a problem, so I decided to somewhat normalize the field input by setting it to lowercase before it's saved in the database.

The Solution

To create a custom form field, you just inherit from the form field class you want to customize. In this case, I want to inherit forms.EmailField.

Inside of forms.py:

# Change email input to lowercase
class CustomEmailField(forms.EmailField):  
    def to_python(self, value):
        return value.lower()


# Visitor Inquiry Form
class InquiryForm(forms.ModelForm):  
    email = CustomEmailField(required=True, max_length=200)

    class Meta:
        model = Visitor
        fields = ['email', ]

You override to_python in your field definition so that the string the person's entered is converted into a python object whenever it's accessed from the database or whenever it's assigned using our custom field. In this case, our to_python method returns the value it was provided into a lowercase string, which is what I wanted.

Conclusion

I now have a custom email field that converts the user input into a lowercase string. Now, even FOObar@foo.com is considered to be a duplicate of foobar@foo.com. That's what I wanted.

I miss you, Renee. Tough Thanksgiving.

Greg

Software Engineer

Subscribe to GregBlogs