我正在尝试在Django中创建Quiz
。有多个问题QuestionForm
。在视图中,我得到Questions
的集合,并为每个对象创建QuestionForm
的列表。然后将此列表发送到模板中,并分别为每个问题呈现文本和表单。
这种方式非常不舒服,我认为必须有一种更简单直接的方法。
主要流程:
当用户进行测试时,会创建Sitting
对象。此对象包含有关用户,测验和预加载问题的信息。当用户回答测验时,会创建SittingQuestion
个对象,其中包含有关问题和用户答案的信息。
如您所见,我为每个表单添加了参数name = question-id
,每个表单的结果为answer-id
。我必须解析id并使用此id创建对象。
我很感激任何帮助以避免解析。
我正在附加QuestionForm
和view
:
QuestionForm
class QuestionForm(forms.Form):
def __init__(self, question, *args, **kwargs):
super(QuestionForm, self).__init__(*args, **kwargs)
choice_list = [(x.pk, x.text) for x in question.get_answers_list()]
self.fields["question-{}".format(question.id)] = forms.ChoiceField(choices=choice_list,
widget=forms.RadioSelect)
查看
def take_quiz(request, id):
if request.method == 'GET':
sitting = models.Sitting.objects.create(quiz=quiz, user=request.user)
sitting.load_questions()
formset = []
for q in sitting.sitting_questions.all():
formset.append((q.question, forms.QuestionForm(q.question)))
return render(request, 'quiz/quiz.html', context={'formset': formset})
quiz = get_object_or_404(models.LanguageQuiz, pk=id)
sitting = get_object_or_404(Sitting,user=request.user,quiz=quiz)
if request.method == 'POST':
for question in request.POST:
question_id = question.split('-')[1]
question_object = get_object_or_404(Question,id=question_id)
answer_id = request.POST[question_id][0]
answer_object = get_object_or_404(Answer,id=answer_id)
SittingQuestion.objects.create(sitting=sitting,question=question_object,answer=answer_object)
模型
class LanguageQuiz(models.Model):
name = models.CharField(max_length=40)
language = models.OneToOneField(sfl_models.Language)
max_questions = models.IntegerField()
time_to_repeat_in_days = models.PositiveIntegerField(default=0)
def __str__(self):
return '{} test'.format(self.name)
def __unicode__(self):
return self.__str__()
class Question(models.Model):
language_quiz = models.ForeignKey(LanguageQuiz,related_name='questions')
text = models.TextField()
def get_answers_list(self):
return self.answers.all()
class Answer(models.Model):
question = models.ForeignKey(Question,related_name='answers',on_delete=models.CASCADE)
text = models.TextField()
correct = models.BooleanField()
class Sitting(models.Model):
user = models.ForeignKey(sfl_models.User, related_name='test_sitting')
quiz = models.ForeignKey(LanguageQuiz)
date_opened = models.DateTimeField(auto_now_add=True)
date_closed = models.DateTimeField(null=True)
closed = models.BooleanField(default=0)
class Meta:
unique_together = ('user','quiz')
def __str__(self):
return 'Sitting - user: {}; quiz: {}'.format(self.user, self.quiz)
def load_questions(self):
questions = random.sample(self.quiz.questions.all(),min(self.quiz.max_questions,len(self.quiz.questions.all())))
for question in questions:
SittingQuestion.objects.create(question=question,sitting=self)
class SittingQuestion(models.Model):
sitting = models.ForeignKey(Sitting, related_name='sitting_questions', on_delete=models.CASCADE)
question = models.ForeignKey(Question, related_name='sitting_questions')
answer = models.ForeignKey(Answer,null=True, blank=True)
答案 0 :(得分:1)
以下是对设计的一种可能的改进:
而不是<div class="shape"></div>
,而是QuestionForm
。将QuizForm
传递给您的表单,并将每个表单设为自己的sitting.sitting_questions.all()
。这样可以更轻松地处理表单。一旦初始化了所需的任何变量,视图中的处理通常就像这样简单:
ChoiceField
无需解析即可获得if request.method == 'POST':
form = QuizForm(request.POST)
if form.is_valid():
# whatever you'd like to do
else: # GET
form = QuizForm(list_of_questions)
,您只需致电question id
或question.id
。
一些阐述:
question.pk
更新:如何在选项之前添加问题文本。
如果您的QuizForm包含所有问题的字段,那么当您遍历字段时,您将获得以下问题字段:class QuizForm(forms.Form):
def __init__(self, questions, *args, **kwargs):
super(QuizForm, self).__init__(*args, **kwargs)
for question in questions:
choice_list = [("QUESTION TEXT", question.text)]
choice_list.append([(x.pk, x.text) for x in question.get_answers_list()])
self.fields["question-{}".format(question.id) = forms.ChoiceField(
choices=choice_list,
widget=forms.RadioSelect
)
。由于{% for question in form %}
是一个字段而不是实际的question
对象,因此我承认您无法在循环中访问Question
。但是,您可以决定将question.text
添加到选项字段(有点破解,但功能正常),我已经将这种可能性包含在上面。然后尝试这样的事情:
question.text
用于渲染按钮:https://docs.djangoproject.com/es/1.9/ref/forms/widgets/#radioselect 我认为关于如何做出选择,SO上已经有很多类似的问题。