Limit Maximum Choices of ManyToManyField

别说谁变了你拦得住时间么 提交于 2020-01-01 08:45:22

问题


I'm trying to limit the maximum amount of choices a model record can have in a ManyToManyField.

In this example there is a BlogSite that can be related to Regions. In this example I want to limit the BlogSite to only be able to have 3 regions.

This seems like something that would have been asked/answered before, but after a couple hours of poking around I haven't been able to find anything close. For this project, I'm 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?


回答1:


You can override clean method on your BlogSite model

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's ModelForm then this error will appear in form's non_field_errors.

EDIT:

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

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)

Give it a try it worked for me.




回答2:


Working! I have used this and its working properly. Validation required before saving the data. So you can use code in form

class BlogSiteForm(forms.ModelForm):
    def clean_regions(self):
        regions = self.cleaned_data['regions']
        if len(regions) > 3:
            raise forms.ValidationError('You can add maximum 3 regions')
        return regions
    class Meta:
        model = BlogSite
        fields = '__all__'



回答3:


The best that I can think of is to have a pre-save signal for BlogSite and check whether this instance of BlogSite has already had 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")


来源:https://stackoverflow.com/questions/20203806/limit-maximum-choices-of-manytomanyfield

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!