11

Trying to solve an interesting problem right now.

I have a Django model with an image field that's not required, but is set to a default value when a new model instance is created.

class Product(models.Model):
    image = models.ImageField(upload_to='/image/directory/', default='/default/image/path/', blank=True)

I also have a ModelForm based on that model, that includes the image field, and that has some custom validation.

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ('image',)

    def clean_image(self):
        image = self.cleaned_data.get('image', False)
        if image:
            # validate image
        return None

The problem is that per the docs, calling is_valid() on a ModelForm triggers model validation in addition to form validation, so when a user submits the model form without an image, my custom form validation code attempts to validate the default model image, rather than just doing nothing as it's supposed to.

How do I get it to not do anything unless the form itself has a value for the image field?

rolling stone
  • 12,668
  • 9
  • 45
  • 63
  • `blank=True` is a validation at the database level, and `null=True` is a validation at the model level, so you need to add `null=True` aswell. – karthikr Oct 09 '12 at 19:13
  • 3
    @karthikr: That's not true. `null is purely database-related, whereas blank is validation-related. If a field has blank=True, form validation will allow entry of an empty value. If a field has blank=False, the field will be required.`. [More info here.](https://docs.djangoproject.com/en/dev/ref/models/fields/#blanko) – ldiqual Oct 09 '12 at 19:16
  • 2
    @karthikr I think you may want to double-check that. From the docs `null is purely database-related, whereas blank is validation-related.` https://docs.djangoproject.com/en/dev/ref/models/fields/#field-options – rolling stone Oct 09 '12 at 19:19

1 Answers1

19

Just solved it in pretty simple way. Adding the answer here in case it's helpful to anyone else.

The Django docs state that

...a model form instance bound to a model object will contain a self.instance attribute that gives model form methods access to that specific model instance.

So rather than check if the ModelForm has an image value, I just check whether the image value has changed from the saved instance. The form validation now looks like this:

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ('image',)

    def clean_image(self):
        image = self.cleaned_data.get('image', False)
        if not self.instance.image == image:
            # validate image
        return None

Problem solved!

C14L
  • 12,153
  • 4
  • 39
  • 52
rolling stone
  • 12,668
  • 9
  • 45
  • 63