Search code examples
djangopython-3.xmonkeypatchingmezzanine

Adding validation to Django User form


I'd like to customize the user sign-up form in Django/Mezzanine to allow only certain email addresses, so I tried to monkey-patch as follows:

# Monkey-patch Mezzanine's user email address check to allow only
# email addresses at @example.com.
from django.forms import ValidationError
from django.utils.translation import ugettext
from mezzanine.accounts.forms import ProfileForm
from copy import deepcopy
original_clean_email = deepcopy(ProfileForm.clean_email)
def clean_email(self):
    email = self.cleaned_data.get("email")
    if not email.endswith('@example.com'):
        raise ValidationError(
            ugettext("Please enter a valid example.com email address"))
    return original_clean_email(self)
ProfileForm.clean_email = clean_email

This code is added at the top of one of my models.py.

However, when I runserver I get the dreaded

django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

If I add

import django
django.setup()

then python manage.py runserver just hangs until I ^C.

What should I be doing to add this functionality?


Solution

  • Create a file myapp/apps.py for one of your apps (I've use myapp here), and define an app config class that does the monkeypatching in the ready() method.

    from django.apps import AppConfig
    
    class MyAppConfig(AppConfig):
        name = 'myapp'
    
        def ready(self):
            # do the imports and define clean_email here
            ProfileForm.clean_email = clean_email
    

    Then use 'myapp.apps.MyAppConfig' instead of 'myapp' in your INSTALLED_APPS setting.

    INSTALLED_APPS = [
        ...
        'myapp.apps.MyAppConfig',
        ...
    ]
    

    You might need to put Mezzanine above the app config for it to work.