Jacob Harding
Jacob Harding

Reputation: 661

Why is my forms clean method not doing anything?

I have two basic models that use model forms in the Django admin. Models.py is similar to:

class FirstModel(models.Model):
    name = CharField(max_length=100)
    url = URLField()
class OtherModel(models.Model):
    model = models.ForeignKey(FirstModel)
    ##Other fields that show up fine and save fine, but include some localflavor

Forms.py looks similar to:

class FirstModelForm(forms.ModelForm):
    def clean(self):
        #call the super as per django docs
        cleaned_data = super(FirstModelForm, self).clean()
        print cleaned_data
    class Meta:
        model = FirstModel
#other modelform is the same with the appropriate word substitutions and one field that gets overridden to a USZipCodeField

These are a stacked inline ModelAdmin with nothing special in the admin.py:

class OtherModelInline(admin.StackedInline):

    model = OtherModel
    fields = (#my list of fields works correctly)
    readonly_fields = (#couple read onlys that work correctly)

class FirstModelAdmin(admin.ModelAdmin):
    inlines = [
        OtherModelInline,
        ]
admin.site.register(FirstModel, FirstModelAdmin)

I do have a User model, form and ModelAdmin that subclasses the User and UserCreationForm and overrides it's own clean method.This works exactly as expected. The problem is with FirstModel and OtherModel. The clean methods I override in the ModelForm subclasses of FirstModelForm and OtherModelForm don't do anything. No exception thrown or a print of the cleaned_data. Just nothing. Everything else works as expected, but it's like my clean method isn't even there. I got to be missing something simple, but I can't see what is. Any help would be great. Thanks!

Upvotes: 1

Views: 2190

Answers (3)

Alasdair
Alasdair

Reputation: 309049

By default, Django dynamically generates a model form for your model admins. You must specify that you want to use your custom forms by setting the form attribute.

class OtherModelInline(admin.StackedInline):

    model = OtherModel
    fields = (...) # if this doesn't work after specifying the form, set fields for the model form instead
    readonly_fields = (#couple read onlys that work correctly)
    form = OtherModelForm

class FirstModelAdmin(admin.ModelAdmin):
    form = FirstModelForm
    inlines = [
        OtherModelInline,
        ]
admin.site.register(FirstModel, FirstModelAdmin)

Upvotes: 1

cardonator
cardonator

Reputation: 396

It is possible that nothing survived the parent 'clean' method. If you are submitting data that won't validate because of the way your models are set up, cleaned_data will be empty. This is mentioned in the same doc linked by Timmy, where it says:

By the time the form’s clean() method is called, all the individual field clean methods will have been run (the previous two sections), so self.cleaned_data will be populated with any data that has survived so far. So you also need to remember to allow for the fact that the fields you are wanting to validate might not have survived the initial individual field checks.

In this case, if you have a URLField, the field validation is very strict, and unless you define 'verify_exists=False', it will also check if you are putting in a URL that returns a 404. In your case you would need to do this if you wanted to allow that:

class FirstModel(models.Model):
    name = CharField(max_length=100)
    url = URLField(verify_exists=False)

Outside of that, I have no idea what could be going on.

Upvotes: 0

Timmy O'Mahony
Timmy O'Mahony

Reputation: 53998

You need to return the cleaned_data from the clean method in the form. If you look at the documentation for cleaning fields that rely on each other you'll notice:

...
# Always return the full collection of cleaned data.
return cleaned_data

Upvotes: 0

Related Questions