1

I couldn't find an answer to the following question, it took me a couple of hours to find out, hence I'm adding it. I'll add my approach of solving it and the answer.

I'm following a YouTube tutorial from This person. For some reason I'm typing the same code, and I checked every single letter. Yet for some reason my cleaning functions aren't called. It's probably something simple, especially since a related question showed something similar. It's probably a framework thing that I get wrong, but I wouldn't know what it is.

Here is the relevant code.

forms.py (complete copy/paste from his Github)

from django import forms

from .models import SignUp

class ContactForm(forms.Form):
    full_name = forms.CharField(required=False)
    email = forms.EmailField()
    message = forms.CharField()


class SignUpForm(forms.ModelForm):
    class Meta:
        model = SignUp
        fields = ['full_name', 'email']
        ### exclude = ['full_name']

    def clean_email(self):
        email = self.cleaned_data.get('email')
        email_base, provider = email.split("@")
        domain, extension = provider.split('.')
        # if not domain == 'USC':
        #   raise forms.ValidationError("Please make sure you use your USC email.")
        if not extension == "edu":
            raise forms.ValidationError("Please use a valid .EDU email address")
        return email

    # Final part is ommited, since it's not relevant.

admin.py (typed over from the tutorial)

from django.contrib import admin

# Register your models here.
from .models import SignUp
from .forms import SignUpForm

class SignUpAdmin(admin.ModelAdmin):
    list_display = ['__unicode__', 'timestamp', 'updated']

    class Meta:
        model = SignUp
        form = SignUpForm

admin.site.register(SignUp, SignUpAdmin)
Community
  • 1
  • 1
Melvin Roest
  • 1,392
  • 1
  • 15
  • 31

1 Answers1

1

After using print statements for a while and reading questions that seemed similar but eventually didn't solve my problem, I decided to look into the source of Django (idea inspired by the most similar question I could find).

Then, I decided to debug the source, since I wanted to know how Django is treating my customized function (thanks to a tutorial + SO answer). In the source I found that the customized functions were called around return super(EmailField, self).clean(value) (line 585, django/forms/fields.py, Django 1.8). When I was stepping through the code I found the critical line if hasattr(self, 'clean_%s' % name): (line 409, django/forms/forms.py, Django 1.8). I checked for the value name which was "email". Yet, the if-statement evaluated as False ((Pdb) p hasattr(self, 'clean_%s' % name)). I didn't understand why, until I figured out that the function name was not registered ((Pdb) pp dir(self)).

I decided to take a look at the whole source code repository and cross-checked every file and then I found that

class Meta:
    model = SignUp
    form = SignUpForm

means that form / SignUpForm were nested inside the Meta class. At first, I didn't think much of it but slowly I started to realize that it should be outside the Meta class while staying main class (SignUpAdmin).

So form = SignUpForm should have been idented one tab back. For me, as a Django beginner, it still kind of baffles me, because I thought the Meta class was supposed to encapsulate both types of data (models and forms). Apparently it shouldn't, that's what I got wrong.

Community
  • 1
  • 1
Melvin Roest
  • 1,392
  • 1
  • 15
  • 31
  • No. You didn't need to delete the Meta class. The important thing is that you imply the clean_email method was nested *inside* the Meta class, whereas it should be outside of that but within the main form class. – Daniel Roseman Aug 21 '16 at 19:01
  • Yes, nested inside is the word group that I should use. Thanks :) – Melvin Roest Aug 21 '16 at 19:02
  • 1
    Holy good god, I never would have figured this out on my own...I had my clean() method inside the form's Meta class as well. THANK YOU! – Casey L Feb 25 '21 at 22:10