我遇到错误django.forms.utils.ValidationError: ['ManagementForm data is missing or has been tampered with']
的问题,但这仅在测试我的代码时发生。当使用真实的POST请求呈现实际网页时,它不会引发此错误。
我有一个名为Position的模型,该表单集由其Candidate-objects组成。因此,对于一个特定职位,我可能有4个候选人。
models.py
class Candidate(models.Model):
user = models.ForeignKey(User, related_name="candidate")
votes = models.PositiveIntegerField(verbose_name="Antall stemmer", blank=True, default=0)
class Position(models.Model):
# Candidates running for position
candidates = models.ManyToManyField(Candidate, blank=True, related_name="positions")
# Number of people voting
number_of_voters = models.PositiveIntegerField(default=0, verbose_name="Antall stemmesedler avgitt")
forms.py
class AddPrevoteForm(forms.ModelForm):
class Meta:
model = Position
fields = ['number_of_voters']
class AddPreVoteToCandidateForm(forms.ModelForm):
class Meta:
model = Candidate
fields = ['votes']
def __init__(self, *args, **kwargs):
super(AddPreVoteToCandidateForm, self).__init__(*args, **kwargs)
self.fields['votes'].label = self.instance.user.get_full_name()
views.py
@permission_required('elections.add_election')
@login_required
def admin_register_prevotes(request, pk):
# Fetch position
position = get_object_or_404(Position, pk=pk)
# For for editing total number of people prevoting
prevote_form = AddPrevoteForm(request.POST or None, instance=position)
# Form for adjusting individual candidate's votes
CandidateFormSet = modelformset_factory(
Candidate, form=AddPreVoteToCandidateForm, extra=0
)
formset = CandidateFormSet(
request.POST or None,
queryset=position.candidates.all()
)
if request.method == 'POST':
if formset.is_valid() and prevote_form.is_valid():
for form in formset:
# Increment both candidate and positions votes
candidate_pk = form.instance.pk
candidate = Candidate.objects.get(pk=candidate_pk)
old_votes = candidate.votes
new_votes = form.cleaned_data['votes']
position.total_votes += (new_votes - old_votes)
form.save()
prevote_form.save()
return redirect(reverse(
'elections:admin_register_candidates',
kwargs={'pk': position.id}
))
context = {
'prevote_form': prevote_form,
'candidate_formset': formset,
'position': position
}
return render(
request, 'elections/admin/admin_add_prevotes.html',
context
)
和模板
<form method="POST">{% csrf_token %}
{{ candidate_formset.management_form }}
{% for candidate_form in candidate_formset %}
<div>
{{ candidate_form }}
</div>
{% endfor %}
{{ prevote_form }}
<div>
<input class="button is-success" type="submit" value="Add prevotes!"></input>
</div>
</form>
从模板得到的formset
如下所示:
<input type="hidden" name="form-TOTAL_FORMS" value="4" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="4" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS" />
<tr><th><label for="id_form-0-votes">Sindre Bakke:</label></th><td><input type="number" name="form-0-votes" value="3" min="0" id="id_form-0-votes" /><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></td></tr> <tr><th><label for="id_form-1-votes">Christopher Massey:</label></th><td><input type="number" name="form-1-votes" value="2" min="0" id="id_form-1-votes" /><input type="hidden" name="form-1-id" value="2" id="id_form-1-id" /></td></tr> <tr><th><label for="id_form-2-votes">Ann Green:</label></th><td><input type="number" name="form-2-votes" value="0" min="0" id="id_form-2-votes" /><input type="hidden" name="form-2-id" value="3" id="id_form-2-id" /></td></tr> <tr><th><label for="id_form-3-votes">Michelle Murray:</label></th><td><input type="number" name="form-3-votes" value="0" min="0" id="id_form-3-votes" /><input type="hidden" name="form-3-id" value="4" id="id_form-3-id" /></td></tr>
这就是为什么我尝试了以下测试(post_data
中的四个第一个来自management_form
)
@pytest.mark.django_db
def test_add_pre_votes_to_candidate(
client, create_admin_user,
create_open_election_with_position_and_candidates):
admin = create_admin_user
client.login(username=admin.username, password='defaultpassword')
election = create_open_election_with_position_and_candidates
position = election.positions.all().first()
number_of_candidates = position.candidates.all().count()
candidate = position.candidates.all().first()
post_data = {
'form-TOTAL_FORMS:': '4',
'form-INITIAL_FORMS': '4',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-votes': '3',
'form-0-id': 1,
'form-1-votes': '2',
'form-1-id': 2,
'form-2-votes': '0',
'form-2-id': 3,
'form-3-votes': '0',
'form-3-id': 4,
'number_of_voters': '0'
}
client.post(
reverse(
'elections:admin_register_prevotes',
kwargs={'pk': position.id}
),
data=post_data
)
任何帮助将不胜感激!
答案 0 :(得分:1)
这通常是由于“管理”表单存在一些问题。
post_data
中似乎有一个错字,'form-TOTAL_FORMS:'
在字符串的末尾有一个额外的:
。
此外,在单元测试中使用隐式主键时要小心。取决于提供Candidates
对象的固定装置的实现,它们在数据库中的ID可能并不总是以1,2等开头。