2016-07-14 3 views
0

Я пытаюсь создать Quiz в Django. Существует несколько вопросов и QuestionForm. В представлении я получаю набор Questions и создаю список QuestionForm s для каждого объекта. Затем этот список отправляется в шаблон и визуализирует текст и форму для каждого вопроса отдельно.Как правильно получать данные из списка форм?

Этот способ очень неудобен, и я думаю, что для этого должен быть более простой и понятный способ.

Основной поток:

Когда пользователь берет тест, объект Sitting создается. Этот объект содержит информацию о пользователе, викторине и заданных вопросах. Когда пользователь отвечает на викторину, создается SittingQuestion объектов, содержащих информацию о вопросе и ответе пользователя.

Как вы можете видеть, я добавил параметр name = question-id для каждой формы, и результат каждой формы - answer-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) 

ответ

1

Вот один из возможных усовершенствований в конструкции:

Вместо 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.

некоторые разработки:

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 
      ) 

Update: Как добавить вопрос текст перед опциями.

Если у вашего QuizForm есть поля, на которые все вопросы, то при переходе по полю вы получите следующие поля вопросов: {% for question in form %}. Поскольку question является полем, а не фактическим Question объектом, я признаю, что вы не можете просто получить доступ к question.text в цикле. Однако вы можете добавить question.text в поле выбора (немного хак-иш, но функционально), я включил эту возможность выше.Тогда попробуйте что-то вроде этого:

{% for question in form %} 
{% for id, text in question.field.choices %} 
{% if id == 'QUESTION TEXT' %} 
    {{ text }} 
{% else %} 
    <!-- render however you like --> 
{% endif %} 
{% endfor %} 
{% endfor %} 

Для кнопок рендеринга: https://docs.djangoproject.com/es/1.9/ref/forms/widgets/#radioselect Я думаю, что есть много подобных вопросов на SO уже, как сделать выбор.

+0

Спасибо, но это проблема. Я не могу понять, как создавать формы вопросов внутри формы викторины. Не могли бы вы рассказать об этом, пожалуйста? –

+0

Вы пробовали цикл for? для вопросов в вопросах: choice_list = ... и self.fields ... = forms.ChoiceField ...? Кроме того, вопросы не должны быть формами, они должны быть полями формы викторины. –

+0

Да, это хорошо, но еще одна вещь. Я не могу понять, как поставить текст для каждого вопроса перед радиоселекциями. Я могу перебирать QuizForm, как {% для ответов в форме%} {{form}} {% endfor%}, которая отображает радиообъекты наборов ответов, но нет способа разместить там текст вопроса перед каждым набором. Я пробовал {% for ....%} {{answer.question.text}} и т. Д. Но ничего не работает ... –

Смежные вопросы