首页 > 解决方案 > django:在保存到数据库之前验证多对多关系的计数

问题描述

我有点卡在我的 django 项目中。我想做以下事情:我有两个模型(省略了不必要的部分):

楷模

class UserGroup(models.Model):
  max_users = IntegerField()
  
  @property
  def user_count(self):
    return len(self.user_set.objects.all())

class User(models.Model):
  groups = models.ManyToManyField(UserGroup)

  def clean(self):
    if self.abschnitt.count() > 2:
      return ValidationError("only two groups allowed")

形式

class RegisterForm(ModelForm):
    class Meta:
        model = user
        fields = ['usergroup']
        widgets = {'usergroup': CheckboxSelectMultiple()}

    def clean_usergroup(self):
        qs = self.cleaned_data['usergroup']
        a = len(qs)
        if len(qs) > 2:
            raise ValidationError("Your group limit is 2")
        return qs

用户组可以定义,通常有 3 到 5 个,每个UserGroup组有最多可以加入的用户。然而,一个用户可以加入多个群组,但他应该被限制最多加入 2 个群组。

用户可以通过从模型生成的User模型表单来选择他的组。

我的方法是覆盖clean()表单的方法和表单的方法clean_groups(),但我总是遇到问题,当重新加载表单时出现异常: ValueError: "<User: User object (None)>" needs to have a value for field "id" before this many-to-many relationship can be used.

我知道这是有道理的,因为没有可以检查的已保存 m2m 关系,因此我宁愿尝试在保存表单之前对其进行验证,但不幸的是,这不起作用。

这是呈现表单的视图:

def index(request):
    if request.method == 'POST':
        f = RegisterForm(request.POST)
        if f.is_valid(): # <- exception occurs here or one line below
            new_user = f.save(commit=False)
            # adding some metadata to the object, not relevant for m2m, but commit = False is required for that
            return render(request, 'registration/preregister_done.html')
    else:
        f = RegisterForm()
             

    return render(request, 'register/index.html', {'form': f})

是否有可能验证用户不检查超过 2 个组而不将其存储在数据库中?

标签: pythondjangodjango-modelsdjango-forms

解决方案


我找到了一个可行的解决方案:

经过一点调试,我发现在调用f.is_valid()模型验证时也会运行。我为pk添加了一个小验证。我改变了这样的模型验证:

def clean(self):
    if self.pk:  # <-- this was missing
        if self.usergroup.count() > 2:
            return ValidationError("only two groups allowed")

现在表单验证使用 f.is_valid() 可以顺利运行。


推荐阅读