如何从表格列表中正确接收数据?

时间:2016-07-14 07:10:41

标签: django django-models django-forms

我正在尝试在Django中创建Quiz。有多个问题QuestionForm。在视图中,我得到Questions的集合,并为每个对象创建QuestionForm的列表。然后将此列表发送到模板中,并分别为每个问题呈现文本和表单。

这种方式非常不舒服,我认为必须有一种更简单直接的方法。

主要流程:

当用户进行测试时,会创建Sitting对象。此对象包含有关用户,测验和预加载问题的信息。当用户回答测验时,会创建SittingQuestion个对象,其中包含有关问题和用户答案的​​信息。

如您所见,我为每个表单添加了参数name = question-id,每个表单的结果为answer-id。我必须解析id并使用此id创建对象。

我很感激任何帮助以避免解析。

我正在附加QuestionFormview

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)

1 个答案:

答案 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 idquestion.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上已经有很多类似的问题。