几天来,我一直一头扎进砖墙上,是时候向比我更聪明、更有经验的人寻求建议了。
背景:作为我的网络应用程序的一部分,我正在构建一个测验应用程序,用户可以在其中回答由多项选择题组成的测验。这些问题都是用户生成的,所以我同时遇到了几个有趣的问题:
a)我必须动态构建测验问题表单(radioselect 小部件)。由于答案选项和问题文本都是用户生成的(模型“问题”和“答案”),我必须在视图中运行查询,然后将变量传递给表单的 init。这样我就可以填充选项并用问题文本覆盖标签:
来自forms.py:
#it's not very clean, there's a lot of legacy code in there...
class AnsweredQuestionForm(forms.ModelForm):
class Meta:
model = AnsweredQuestion
widget = {
'id': forms.TextInput, # needed for formset that I was using
}
question_field = forms.ModelChoiceField(
empty_label='Gee, this is tough. Can you show me some hints?',
widget=forms.RadioSelect,
queryset=Question.objects.all(),
required=True,
help_text='',
error_messages={'required': 'Please pick an answer'},
)
def __init__(self, *args, **kwargs): # I'm using django crispy-forms
self.helper = FormHelper()
self.helper.form_method = 'POST'
self.helper.form_id = ''
self.helper.form_class = ''
self.helper.form_action = ''
self.helper.form_tag = False
self.helper.help_text_inline = True
self.helper.render_unmentioned_fields = False
self.helper.form_error_title = 'Form Errors'
self.helper.layout = Layout(
Field('question_field'),
Field('id', css_class='hidden'),
)
self.question = kwargs.pop('question', None)
super(AnsweredQuestionForm, self).__init__(*args, **kwargs)
self.fields['question_field'].label = self.question.question_text
self.fields['question_field'].queryset = self.question.answers.all()
b)这意味着测验问题形式是模型形式(我有一个名为“AnsweredQuestions”的模型,它保存给定答案的实例。还有一个用于测验的模型“TakenQuiz”)。我在用户开始测验时创建了 TakenQuiz 的实例,并在她回答测验问题并保存表单时创建了 AnsweredQuestion 的实例。
来自模型.py
class AnsweredQuestion(models.Model):
question = models.ForeignKey(Question, null=True, blank=True)
given_answer = models.ForeignKey(Answer, null=True, blank=True)
taken_quiz = models.ForeignKey(TakenQuiz, related_name="answered_questions", null=True, blank=True)
date = models.DateTimeField(editable=False)
correct = models.BooleanField(default=False)
class Meta:
verbose_name = 'answered question'
verbose_name_plural = 'answered questions'
def save(self, *args, **kwargs):
""" On save, update timestamp."""
if not self.id:
self.date = datetime.datetime.now()
super(AnsweredQuestion, self).save(*args, **kwargs)
def __unicode__(self):
return unicode(self.given_answer)
从views.py(测试视图):
def take_quiz(request, category_slug, course_slug, module_slug, quiz_number):
user = request.user
category = Category.objects.get(slug=category_slug)
course = Course.objects.get(category=category, slug=course_slug)
module = Module.objects.get(course=course, slug=module_slug)
quiz = module.quizzes.get(number=quiz_number)
quiz_questions = Question.objects.filter(quiz=quiz)
...
else:
taken_quiz = TakenQuiz()
aq_form = AnsweredQuestionForm(question=question)
c) 一个测验可以由可变数量的测验问题组成,我只设置了一个最大限制。所以几乎一切都是动态的:(
所以这是我的具体问题:
如果我使用表单向导,如何访问 URL 参数并将它们用于我的查询?(顺便说一句,我讨厌基于类的通用视图)我试图使问题的数量动态化,但还没有弄清楚如何将变量 (len(quiz_questions) 传递给向导...我的网址如下所示,不幸的是,我需要将所有这些都传递给模板上下文或表单的 init:
来自 urls.py:
url(r'^(?P<category_slug>[-\w]+)/(?P<course_slug>[-\w]+)/(?P<module_slug>[-\w]+)/(?P<quiz_number>\d+)/$', quiz_wizard, name='quiz_wizard'), quiz_wizard = QuizWizard.as_view(named_quiz_forms) named_quiz_forms = [('quiz_question_%d' % i, AnsweredQuestionForm) for i in xrange(0, len(quiz_questions))]
我是否应该费心尝试弯曲表单向导来做我需要的事情?我花了很多时间在谷歌研究和源代码上,我找到了一些问题的潜在解决方案,但不是全部。尤其是不能同时为所有人...
我可能必须至少覆盖所有这些:
class QuizWizard(NamedUrlSessionWizardView): def get_form(self, step=None, data=None, files=None): form = super(QuizWizard, self).get_form(step, data, files) ... return form def get_form_kwargs(self, step): return {} def get_form_instance(self, step): return self.instance_dict.get(step, None)
最后:如果我不能使用表单向导,我应该如何处理测验有什么建议吗?使用 formwizard 对我来说似乎更干净,而不是只为每个测验问题使用视图。该向导的最大优点是在整个测验完成和验证之前,我不必将表单数据保存在某个地方,并且该向导会为我跟踪步骤数和当前步骤。我是一个新手,从头开始编写这种高级的东西并不是很擅长。
非常感谢您的帮助,任何建议或帮助都非常感谢!!