Django自定义模型表单集的ValidationError(数据缺失或已被篡改)

0 投票
1 回答
682 浏览
提问于 2025-04-17 16:40

我正在为一个会员模型(把用户和项目关联起来)制作一个模型表单集合。下面是我在app/forms.py中的代码,我把一些不相关的部分删掉了,确认了这些部分可以注释掉:

class EditMembership(forms.ModelForm):
  delete = forms.BooleanField(required=False, initial=False)

  class Meta:
    model = models.Membership
    fields = ('is_owner',)  

  def clean_delete(self):
    return self.cleaned_data['delete']

class BaseEditMemberships(forms.models.BaseModelFormSet):
  # Some custom methods not dealing with validation.
  pass

EditMembershipSet = forms.models.modelformset_factory(models.Membership,
  form=EditMembership, extra=0, formset=BaseEditMemberships)

这是我的模板:

<form method="{{ method|default:"post" }}" action="{{ action }}">
  {% csrf_token %}
  <ul>
  {% for form in formset %}
    <li>{{ form.instance.user}}</li>
    {{ form.as_ul }}
  {% endfor %}
  </ul>
  <input type="submit" value="{{ submit_value|default:"Submit" }}" />
</form>

这是我的视图:

@ownership_required(message="You must be an owner to edit memberships.")
def edit_memberships(request, pk):
  project = get_object_or_404(models.Project, pk=pk)
  if request.method == "GET":
    formset = forms.EditMembershipSet(
      queryset=project.membership_set.all()
    )
    return render_formset_fullpage(request, formset, "Edit Memberships",
      template=forms.EDITMEMBERSHIPS_PATH)
  elif request.method == "POST":
    formset = forms.EditMembershipSet(request.POST)
    return HttpResponse("Hooray!")

还有我提到的模型:

class Membership(models.Model):
  class Meta:
    unique_together = ('project', 'user')

  project = models.ForeignKey('common.Project', editable=False)
  user = models.ForeignKey('auth.User')
  is_owner = models.BooleanField(default=False, blank=False,
    help_text="Indicates ownership of the project")
  project_alias = models.CharField(max_length=CHARFIELD_SHORT,
    help_text="User-given name", blank=True)

问题是我在提交表单后总是收到一个验证错误:

ValidationError at /project/4/memberships
[u'ManagementForm data is missing or has been tampered with']

根据我的观察,forms.EditMembership这个表单是正常的。我可以正常渲染这个表单,并且在提交后也没有验证错误,所以我猜可能是我使用BaseEditMemberships/EditMembershipSet的方式出了问题。

补充:

为了提供更多信息,这里有一个生成的示例表单和我测试请求的POST变量。这个表单:

<form method="post" action="">
  <div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='d6d535efd35e83076e1ac14a82ef4cdc' /></div>
  <ul> 
    <li>someuser</li>
    <li><label for="id_form-0-is_owner">Is owner:</label>
      <input checked="checked" type="checkbox" name="form-0-is_owner" id="id_form-0-is_owner" />
    </li>
<li><label for="id_form-0-delete">Delete:</label>
  <input type="checkbox" name="form-0-delete" id="id_form-0-delete" />
  <input type="hidden" name="form-0-id" value="8" id="id_form-0-id" />
</li>

  </ul>
  <input type="submit" value="Submit" />
</form>

如果我勾选了删除框,对应的POST变量如下:

  • form-0-id: u'8'
  • csrfmiddlewaretoken: u'd6d535efd35e83076e1ac14a82ef4cdc'
  • form-0-delete: u'on'
  • form-0-is_owner: u'on'

1 个回答

2

你需要在你的模板里加上 {{ formset.management_form }} 这一行。想了解更多,可以看看 Django关于如何在模板中使用表单集合的文档

撰写回答