Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django manytomany validation

Please see the code below. Basically, when the user creates an object of this class, they need to specify the value_type. If value_type==2 (percentage), then percentage_calculated_on (which is a CheckboxSelectMultiple on the form/template side needs to have one or more items checked. The model validation isn't allowing me to validate like I'm trying to -- it basically throws an exception that tells me that the instance needs to have a primary key value before a many-to-many relationship can be used. But I need to first validate the object before saving it. I have tried this validation on the form (modelform) side (using the form's clean method), but the same thing happens there too.

How do I go about achieving this validation?

INHERENT_TYPE_CHOICES = ((1, 'Payable'), (2, 'Deductible'))
VALUE_TYPE_CHOICES = ((1, 'Amount'), (2, 'Percentage'))

class Payable(models.Model):
    name = models.CharField()
    short_name = models.CharField()
    inherent_type = models.PositiveSmallIntegerField(choices=INHERENT_TYPE_CHOICES)
    value = models.DecimalField(max_digits=12,decimal_places=2)
    value_type = models.PositiveSmallIntegerField(choices=VALUE_TYPE_CHOICES)
    percentage_calculated_on = models.ManyToManyField('self', symmetrical=False)

    def clean(self):
        from django.core.exceptions import ValidationError
        if self.value_type == 2 and not self.percentage_calculated_on:
            raise ValidationError("If this is a percentage, please specify on what payables/deductibles this percentage should be calculated on.")
like image 477
chefsmart Avatar asked Oct 04 '10 08:10

chefsmart


1 Answers

I tested out your code in one of my projects' admin app. I was able to perform the validation you required by using a custom ModelForm. See below.

# forms.py
class MyPayableForm(forms.ModelForm):
    class Meta:
        model = Payable

    def clean(self):
        super(MyPayableForm, self).clean() # Thanks, @chefsmart
        value_type = self.cleaned_data.get('value_type', None)
        percentage_calculated_on = self.cleaned_data.get(
             'percentage_calculated_on', None)
        if value_type == 2 and not percentage_calculated_on:
            message = "Please specify on what payables/deductibles ..."
            raise forms.ValidationError(message)
        return self.cleaned_data

# admin.py
class PayableAdmin(admin.ModelAdmin):
    form = MyPayableForm

admin.site.register(Payable, PayableAdmin)

The Admin app uses the SelectMultiple widget (rather than CheckboxSelectMultiple as you do) to represent many to many relationships. I believe this shouldn't matter though.

like image 104
Manoj Govindan Avatar answered Sep 30 '22 08:09

Manoj Govindan