Skip to content Skip to sidebar Skip to footer

Validate Count() Constraint In Many To Many Relation Before Saving An Instance In Django

I would like to prevent a save in a django model when a certain constraint is not met and give a validation error so that a django staff user knows what went wrong. The constraint

Solution 1:

Thanks to @zaidfazil for a starting solution:

classUserProfileGoalForm(forms.ModelForm):
  classMeta:
    model = UserProfileGoal
    ...

  defclean(self):
    cleaned_data = super(UserProfileGoalForm, self).clean()
    if self.instance.pk isnotNone:
      return cleaned_data
    user_profile = self.cleaned_data.get('user_profile')
    goal_count = user_profile.goals.count()
    goal_limit = UserGoalConstraint.objects.get(user_profile=user_profile).max_goals # removed try catch for get for easier readingif goal_count >= goal_limit:
      raise ValidationError('Maximum limit reached for goals')
    return cleaned_data

However, this does not handle the inline in the UserProfile admin interface: clean() won't handle correctly if you add more than one Goal at the same time and press save.

So I applied the UserProfileGoalForm to the inline and defined max_num :

classUserProfileGoalInline(admin.TabularInline):
  model=UserProfileGoal
  form = UserProfileGoalForm

  defget_max_num(self, request, obj=None, **kwargs):
    if obj isNone:
      return
    goal_limit = UserGoalConstraint.objects.get(training_profile=obj).max_goals
    return goal_limit # which will overwrite the inline's max_num attribute

Now my client can only add at maximum the max_goals value from the UserGoalConstraint, and also a possible admin form for UserProfileGoal will handle the constraint:

classUserProfileGoalAdmin(admin.ModelAdmin):
  form = UserProfileGoalForm

Solution 2:

You could handle it in ModelFormclean method,

classGoalForm(forms.ModelForm):
    classMeta:
        model = Goal
        .....

    defclean(self):
        cleaned_data = super(GoalForm, self).clean()
        if self.instance.pk isnotNone:
            return cleaned_data
        goal_limit = self.user_profile.usergoalconstraint.max_goals
        goal_count = self.user_profile.goals.count()
        if goal_count >= goal_limit:
            raise ValidationError("Maximum limit reached for goals")
        return cleaned_data

Post a Comment for "Validate Count() Constraint In Many To Many Relation Before Saving An Instance In Django"