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
.