【发布时间】:2021-07-15 15:47:54
【问题描述】:
好的,我正在学习使用 Django 创建一个小型问卷的教程。
用户可以创建包含不同选择题的调查。由于它们是多项选择题,因此用户还可以设置问题的选项。
“调查员”然后可以开始调查,选择他或她喜欢的问题并提交表格。
我希望每页只显示一个问题,因此我尝试使用 modelformset_factory 并使用内置分页器实现分页。
表单正确呈现,用户可以提交答案,但是表单在“formset.is_valid()”之前失败,我就是不知道为什么;
/surveys/1/submit/4/处的ValueError
无法分配“'2'”:“Answer.option”必须是“Option”实例。
所以我无法保存整数,并且我不得不将整数与选项模型中的 id 关联起来……但我还无法访问cleaned_data,所以我想我在这里遗漏了一些东西。我是否忘记了表单集中的某些内容?
我已经盯着这个看了一段时间,所以感谢任何帮助。
#查看次数
def submit(request, survey_pk, sub_pk):
# Let's retrieve the survey which is created by the survey-taker
try:
survey = Survey.objects.prefetch_related("question_set__option_set").get(
pk=survey_pk, is_active=True
)
except Survey.DoesNotExist:
raise Http404()
try:
submission = survey.submission_set.get(pk=sub_pk, is_complete=False)
except Submission.DoesNotExist:
raise Http404()
# Retrieve all question associated with this survey
questions = survey.question_set.all()
# Get all related options from the questions
options = [q.option_set.all() for q in questions]
form_kwargs = {"empty_permitted": False, "options": options,}
# Setup a formset utilizing a ModelFormSet
AnswerFormset = modelformset_factory(
Answer,
form=AnswerModelForm,
formset=BaseAnswerFormSet,
exclude=(),
extra=len(questions),
)
if request.method == "POST":
print("Request.POST", request.POST)
# This is where the problem starts
formset = AnswerFormset(request.POST, form_kwargs=form_kwargs)
print("Formset: ", formset)
if formset.is_valid():
print("Formset is valid")
with transaction.atomic():
for form in formset:
Answer.objects.create(
option_id=form.cleaned_data["option"],
submission_id=sub_pk,
)
submission.is_complete = True
submission.save
return redirect("survey-thanks", pk=survey_pk)
else:
formset = AnswerFormset(form_kwargs=form_kwargs)
print(form_kwargs)
question_forms = zip(questions, formset)
return render(
request,
"survey/submit.html",
{
"survey": survey,
"question_forms": question_forms,
"formset": formset
}
)
#forms
# Setup a Modelformset
class AnswerModelForm(forms.ModelForm):
class Meta:
model = Answer
fields = "option",
def __init__(self, *args, **kwargs):
options = kwargs.pop("options")
# Options must be a list of Option objects
choices = {(o.pk, o.text) for o in options}
super().__init__(*args, **kwargs)
option_field = forms.ChoiceField(choices=choices, widget=forms.RadioSelect, required=True)
self.fields["option"] = option_field
class BaseAnswerFormSet(forms.BaseFormSet):
def get_form_kwargs(self, index):
kwargs = super().get_form_kwargs(index)
kwargs["options"] = kwargs["options"][index]
return kwargs
#models
class Answer(models.Model):
"""An answer a survey's questions."""
submission = models.ForeignKey(Submission, on_delete=models.CASCADE)
option = models.ForeignKey(Option, on_delete=models.CASCADE)
【问题讨论】:
标签: python django django-forms formset