Limit the maximum selection of ManyToManyField

I am trying to limit the maximum number of options that a model entry in ManyToManyField can have.

In this example, there is a BlogSite that can be associated with regions. In this example, I want to limit the use of BlogSite to only three areas.

This is similar to what would have been asked / answered earlier, but after a couple of hours I was unable to poke anything close. For this project, I am using Django 1.3.

#models.py class BlogSite(models.Model): blog_owner = models.ForeignKey(User) site_name = models.CharField(max_length=300) region = models.ManyToManyField('Region', blank=True, null=True) .... class Region(models.Model): value = models.CharField(max_length=50) display_value = models.CharField(max_length=60) .... 

Any ideas?

+7
django django-models
source share
2 answers

You can override the clean method on your BlogSite model BlogSite

 from django.core.exceptions import ValidationError class BlogSite(models.Model): blog_owner = models.ForeignKey(User) site_name = models.CharField(max_length=300) regions = models.ManyToManyField('Region', blank=True, null=True) def clean(self, *args, **kwargs): if self.regions.count() > 3: raise ValidationError("You can't assign more than three regions") super(BlogSite, self).clean(*args, **kwargs) #This will not work cause m2m fields are saved after the model is saved 

And if you use django ModelForm, this error will appear in the form of non_field_errors.

EDIT:

M2m fields are saved after saving the model, so the above code will not work, the correct way to use the m2m_changed signal m2m_changed :

 from django.db.models.signals import m2m_changed from django.core.exceptions import ValidationError def regions_changed(sender, **kwargs): if kwargs['instance'].regions.count() > 3: raise ValidationError("You can't assign more than three regions") m2m_changed.connect(regions_changed, sender=BlogSite.regions.through) 

Try it to work for me.

+10
source share

The best I can think of is to have a pre-save signal for BlogSite and check if this instance of BlogSite already has 3 regions.

 @receiver(pre_save, sender=BlogSite) def check_regions_limit(sender, instance, **kwargs): if instance.regions.count() == 3: raise_some_exception("Can't add more than 3 regions to a BlogSite") 
0
source share

All Articles