2016-07-14 11 views
0

Ich versuche ein Quiz in Django zu erstellen. Es gibt mehrere Fragen und QuestionForm. In einer Ansicht, ich bekomme Questions Set und erstellen Sie eine Liste von QuestionForm s für jedes Objekt. Dann wird diese Liste in die Vorlage gesendet und Text und Formular für jede Frage getrennt dargestellt.Wie bekomme ich Daten aus der Liste der Formulare richtig?

Dieser Weg ist sehr unangenehm und ich denke, dass es eine einfachere und direktere Möglichkeit geben muss, dies zu tun.

Der Hauptstrom:

Wenn der Benutzer einen Test in Anspruch nimmt, Sitting Objekt wird erstellt. Dieses Objekt enthält Informationen über Benutzer, Quiz und vorinstallierte Fragen. Wenn der Benutzer das Quiz beantwortet, werden SittingQuestion Objekte erstellt, die Informationen über die Frage und die Benutzerantwort enthalten. Wie Sie sehen können, habe ich für jedes Formular einen Parameter name = question-id hinzugefügt und das Ergebnis jedes Formulars ist answer-id. Ich muss IDs analysieren und Objekte mit dieser ID erstellen.

Ich würde jede Hilfe schätzen, besonders zu vermeiden, zu analysieren.

Ich bin ein QuestionForm Anbringen und ein 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) 

Ansicht

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) 

MODELS

Hier
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) 

Antwort

1

ist eine mögliche Verbesserung der Gestaltung:

Statt QuestionForm, eine QuizForm machen. Übergeben Sie sitting.sitting_questions.all() an Ihr Formular, und machen Sie jedes ein eigenes ChoiceField. Dies erleichtert die Verarbeitung Ihres Formulars erheblich. Sobald Sie, was auch immer Variablen initialisieren Sie benötigen, aus der Sicht der Handhabung ist in der Regel so einfach wie diese:

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) 

Es gibt keine Notwendigkeit, die question id zu bekommen zu analysieren ist, können Sie einfach question.id oder question.pk nennen.

einige Ausarbeitung:

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: Wie Fragetext, bevor Optionen hinzuzufügen.

Wenn Ihre QuizForm Felder enthält, die alle Fragen enthalten, erhalten Sie bei der Iteration über Ihr Feld die folgenden Fragenfelder: . Da question ist ein Feld und nicht das eigentliche Question Objekt, ich gebe zu, Sie können nicht einfach zugreifen question.text in der Schleife. Sie können jedoch entscheiden, question.text zu dem Auswahlfeld hinzuzufügen (ein wenig hack-ish, aber funktional), ich habe diese Möglichkeit oben enthalten.Dann versuchen Sie so etwas wie dieses:

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

Für Rendering-Tasten: https://docs.djangoproject.com/es/1.9/ref/forms/widgets/#radioselect Ich denke, es gibt viele ähnliche Fragen auf SO bereits, wie die Entscheidungen zu machen.

+0

Danke, aber das ist das Problem. Ich kann nicht herausfinden, wie man Frageformen innerhalb der Quizform bildet. Können Sie es bitte erläutern? –

+0

Haben Sie eine for-Schleife ausprobiert? für Fragen in Fragen: ChooseField ...? Auch sollten die Fragen keine Formulare sein, sie sollten Formularfelder der Quizform sein. –

+0

Ja, das ist schön, aber noch eine Sache. Ich kann nicht herausfinden, wie man den Text für jede Frage vor die Radioauswahl stellt. Ich kann über QuizForm wie {% für Antworten im Formular%} {{form}} {% endfor%} iterieren, was Radiobuttons von Antwortsätzen anzeigt, aber es gibt keinen Weg, einen Text der Frage vor jedem Satz zu platzieren. Ich habe versucht {% for ....%} {{answer.question.text}} usw. aber nichts scheint zu funktionieren ... –

Verwandte Themen