Django's ModelForm unique_together validation

I solved this same problem by overriding the validate_unique() method of the ModelForm:


def validate_unique(self):
    exclude = self._get_validation_exclusions()
    exclude.remove('problem') # allow checking against the missing attribute

    try:
        self.instance.validate_unique(exclude=exclude)
    except ValidationError, e:
        self._update_errors(e.message_dict)

Now I just always make sure that the attribute not provided on the form is still available, e.g. instance=Solution(problem=some_problem) on the initializer.


As Felix says, ModelForms are supposed to check the unique_together constraint in their validation.

However, in your case you are actually excluding one element of that constraint from your form. I imagine this is your problem - how is the form going to check the constraint, if half of it is not even on the form?


I managed to fix this without modifying the view by adding a clean method to my form:

class SolutionForm(forms.ModelForm):
    class Meta:
        model = Solution
        exclude = ['problem']

    def clean(self):
        cleaned_data = self.cleaned_data

        try:
            Solution.objects.get(name=cleaned_data['name'], problem=self.problem)
        except Solution.DoesNotExist:
            pass
        else:
            raise ValidationError('Solution with this Name already exists for this problem')

        # Always return cleaned_data
        return cleaned_data

The only thing I need to do now in the view is to add a problem property to the form before executing is_valid.