我正在尝试限制模型记录在ManyToManyField中可以选择的最大数量。
在此示例中,有一个可以与Regions相关的BlogSite。在这个例子中,我想限制BlogSite只能有3个区域。
这似乎是之前会被问及/回答的事情,但经过几个小时的探索之后,我找不到任何接近的东西。对于这个项目,我正在使用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)
....
有什么想法吗?
答案 0 :(得分:10)
您可以在clean
型号
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
如果你使用django的ModelForm,那么这个错误将出现在表单的non_field_errors中。
编辑:
保存模型后会保存M2m字段,因此上述代码无效,您可以使用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)
尝试一下它对我有用。
答案 1 :(得分:2)
工作!我已经使用了它,并且工作正常。 保存数据之前需要验证。所以您可以使用表单中的代码
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__'
答案 2 :(得分:0)
我能想到的最好的方法是为BlogSite提供预保存信号,并检查BlogSite的这个实例是否已经有3个区域。
@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")