views:

123

answers:

2

I have a Django model for a sweater and want to be able to enter the composition of materials used in the admin panel (say: "100% wool" or "50% wool, 50% cotton" or "50% wool, 45% cotton, 5% acryl").

I have this model:

class Sweater(models.Model):
         wool   = models.IntegerField(max_length=3, default=100, verbose_name="wool (%)")
         cotton = models.IntegerField(max_length=3, default=0, verbose_name="cotton (%)")
         acryl  = models.IntegerField(max_length=3, default=0, verbose_name="acryl (%)")

How and where do I assert that the sum of the wool, cotton and acryl values must be 100 so that a user can't enter for example "100% wool, 100% cotton, 100% acryl"?

+1  A: 

In the development version of Django you can write a form validator, and then specify it using "validator_list" argument on one the fields.

If you are using Django 1.1 or below you can override ModelForm as suggested in the answer to this question.

You can read more about form validation in the documentation.

Ludwik Trammer
+2  A: 

You should likely do it in at least two places. One to make sure you don't get incorrect data in the model and one to let the user know the sum does not add up to 100%. The below handles checking the sum during form cleaning:

class SweaterForm(ModelForm):
    """Form for adding and updating sweaters."""

    def clean(self):
        cleaned_data = self.cleaned_data
        wool = cleaned_data.get('wool')
        cotton = cleaned_data.get('cotton')
        acryl = cleaned_data.get('acryl')

        # Check that the fabric composition adds up to 100%
        if not 'wool' in self._errors \
                and not 'cotton' in self._errors \
                and not 'acryl' in self._errors \
                and (wool + cotton + acryl) != 100:
            msg = u"Composition must add up to 100%!"
            self._errors['wool'] = ErrorList([msg])

            # Remove field from the cleaned data as it is no longer valid
            del cleaned_data['wool']

        return cleaned_data

    class Meta:
        model = Sweater

Hope that helps!

lemonad