0

I am new to Django. This is technically my first project.

I am building a quiz web app in Django, using tomwalker's quiz app I would like to present the questions on a card, when a user answers the question the card shall flip and show the explanation of question and correct answer.

How to populate backside of card with answer explanation, after the user submits his/her answer?

In my current implementation, when the user clicks on submit button (to submit the answer), the page reloads with next question and the flip side of the card is not shown.

questions.html TEMPLATE BODY:

<body>
{% load i18n%}
{% if question %}
    <form action="" method="POST">
    {% csrf_token %}
    <section class="container">
      <div class="card"">
        <div class="front">
            <p>
                <small class="muted">{% trans "Question category" %}:</small>
                <strong>{{ question.category }}</strong>
            </p>
             <p class="lead">{{ question.content }}</p>
             {% if question.figure %}
                 <img src="{{ question.figure.url }}" alt="{{ question.content }}" />
             {% endif %}
             <input type=hidden name="question_id" value="{{ question.id }}">
                  <ul class="list-group">
                    {% for answer in form.answers %}
                      <li class="list-group-item">
                        {{ answer }}
                      </li>
                    {% endfor %}
                </ul>
            <input onclick="flip()" type="submit" value={% trans "Next" %} class="btn btn-large btn-block btn-warning" >

        </div>
        <div class="back">
            <p>
                <small class="muted">{% trans "Explaination" %}:</small>
                <strong>{{ question.explanation}}</strong>
            </p>
            <p>
                <small class="muted">{% trans "Correct answer" %}:</small>
                <strong>{{ correct_answer}}</strong>
            </p>
            <button onclick="flip()">flip back</button>
        </div>
      </div>
    </section>
    </form>
{% endif %}
</body>

JS CODE FOR FLIPPING THE CARD:

function flip() {
    $('.card').toggleClass('flipped');
}

FORM VIEW:

class QuizTake(FormView):
form_class = QuestionForm
template_name = 'quiz\questions.html'

def dispatch(self, request, *args, **kwargs):
    self.quiz = get_object_or_404(Quiz, url=self.kwargs.get('quiz_url'))
    if self.quiz.draft and not request.user.has_perm('quiz.change_quiz'):
        raise PermissionDenied

    self.logged_in_user = self.request.user.is_authenticated()

    if self.logged_in_user:
        self.sitting = Sitting.objects.user_sitting(request.user,
                                                    self.quiz)
    else:
        self.sitting = self.anon_load_sitting()

    if self.sitting is False:
        return render(request, 'quiz\single_complete.html')

    return super(QuizTake, self).dispatch(request, *args, **kwargs)

def get_form(self, form_class = None):

    if form_class is None:
        form_class = self.get_form_class()

    if self.logged_in_user:
        self.question = self.sitting.get_first_question()
        self.progress = self.sitting.progress()
    else:
        self.question = self.anon_next_question()
        self.progress = self.anon_sitting_progress()

    # if self.question.__class__ is Essay_Question:
    #     form_class = EssayForm

    return form_class(**self.get_form_kwargs())

def get_form_kwargs(self):
    kwargs = super(QuizTake, self).get_form_kwargs()

    return dict(kwargs, question=self.question)

def form_valid(self, form):
    if self.logged_in_user:
        self.form_valid_user(form)
        if self.sitting.get_first_question() is False:
            return self.final_result_user()
    else:
        self.form_valid_anon(form)
        if not self.request.session[self.quiz.anon_q_list()]:
            return self.final_result_anon()

    self.request.POST = {}

    return super(QuizTake, self).get(self, self.request)

def get_context_data(self, **kwargs):
    context = super(QuizTake, self).get_context_data(**kwargs)
    context['question'] = self.question
    context['quiz'] = self.quiz
    if hasattr(self, 'previous'):
        context['previous'] = self.previous
    if hasattr(self, 'progress'):
        context['progress'] = self.progress
    return context

def form_valid_user(self, form):
    # progress, c = Progress.objects.get_or_create(user=self.request.user)
    guess = form.cleaned_data['answers']
    is_correct = self.question.check_if_correct(guess)

    if is_correct is True:
        self.sitting.add_to_score(1)
        # progress.update_score(self.question, 1, 1)
    else:
        self.sitting.add_incorrect_question(self.question)
        # progress.update_score(self.question, 0, 1)

    if self.quiz.answers_at_end is not True:
        self.previous = {'previous_answer': guess,
                         'previous_outcome': is_correct,
                         'previous_question': self.question,
                         'answers': self.question.get_answers(),
                         'question_type': {self.question
                                               .__class__.__name__: True}}
    else:
        self.previous = {}

    self.sitting.add_user_answer(self.question, guess)
    self.sitting.remove_first_question()

def final_result_user(self):
    results = {
        'quiz': self.quiz,
        'score': self.sitting.get_current_score,
        'max_score': self.sitting.get_max_score,
        'percent': self.sitting.get_percent_correct,
        'sitting': self.sitting,
        'previous': self.previous,
    }

    self.sitting.mark_quiz_complete()

    if self.quiz.answers_at_end:
        results['questions'] = \
            self.sitting.get_questions(with_answers=True)
        results['incorrect_questions'] = \
            self.sitting.get_incorrect_questions


    if self.quiz.exam_paper is False:
        self.sitting.delete()

    return render(self.request, 'quiz\result.html', results)

def anon_load_sitting(self):
    if self.quiz.single_attempt is True:
        return False

    if self.quiz.anon_q_list() in self.request.session:
        return self.request.session[self.quiz.anon_q_list()]
    else:
        return self.new_anon_quiz_session()

def new_anon_quiz_session(self):
    """
    Sets the session variables when starting a quiz for the first time
    as a non signed-in user
    """
    self.request.session.set_expiry(259200)  # expires after 3 days
    questions = self.quiz.get_questions()
    question_list = [question.id for question in questions]

    if self.quiz.random_order is True:
        random.shuffle(question_list)

    if self.quiz.max_questions and (self.quiz.max_questions
                                        < len(question_list)):
        question_list = question_list[:self.quiz.max_questions]

    # session score for anon users
    self.request.session[self.quiz.anon_score_id()] = 0

    # session list of questions
    self.request.session[self.quiz.anon_q_list()] = question_list

    # session list of question order and incorrect questions
    self.request.session[self.quiz.anon_q_data()] = dict(
        incorrect_questions=[],
        order=question_list,
    )

    return self.request.session[self.quiz.anon_q_list()]

def anon_next_question(self):
    next_question_id = self.request.session[self.quiz.anon_q_list()][0]
    return Question.objects.get_subclass(id=next_question_id)

def anon_sitting_progress(self):
    total = len(self.request.session[self.quiz.anon_q_data()]['order'])
    answered = total - len(self.request.session[self.quiz.anon_q_list()])
    return (answered, total)

def form_valid_anon(self, form):
    guess = form.cleaned_data['answers']
    is_correct = self.question.check_if_correct(guess)

    if is_correct:
        self.request.session[self.quiz.anon_score_id()] += 1
        anon_session_score(self.request.session, 1, 1)
    else:
        anon_session_score(self.request.session, 0, 1)
        self.request \
            .session[self.quiz.anon_q_data()]['incorrect_questions'] \
            .append(self.question.id)

    self.previous = {}
    if self.quiz.answers_at_end is not True:
        self.previous = {'previous_answer': guess,
                         'previous_outcome': is_correct,
                         'previous_question': self.question,
                         'answers': self.question.get_answers(),
                         'question_type': {self.question
                                               .__class__.__name__: True}}

    self.request.session[self.quiz.anon_q_list()] = \
        self.request.session[self.quiz.anon_q_list()][1:]

def final_result_anon(self):
    score = self.request.session[self.quiz.anon_score_id()]
    q_order = self.request.session[self.quiz.anon_q_data()]['order']
    max_score = len(q_order)
    percent = int(round((float(score) / max_score) * 100))
    session, session_possible = anon_session_score(self.request.session)
    if score is 0:
        score = "0"

    results = {
        'score': score,
        'max_score': max_score,
        'percent': percent,
        'session': session,
        'possible': session_possible
    }

    del self.request.session[self.quiz.anon_q_list()]

    if self.quiz.answers_at_end:
        results['questions'] = sorted(
            self.quiz.question_set.filter(id__in=q_order)
                .select_subclasses(),
            key=lambda q: q_order.index(q.id))

        results['incorrect_questions'] = (
            self.request
                .session[self.quiz.anon_q_data()]['incorrect_questions'])

    else:
        results['previous'] = self.previous

    del self.request.session[self.quiz.anon_q_data()]

    return render(self.request, 'result.html', results)
Addy
  • 1
  • 1
  • What is your question? – Håken Lid Sep 13 '17 at 21:07
  • @HåkenLid I just edited the question, to add more information. Tried to clarify what i am looking for. Also added some code. Any help will be highly appreciated. Borrowing Card flip logic from : https://jsfiddle.net/james2doyle/qsQun/ – Addy Sep 13 '17 at 21:36
  • You are asking if this is the right approach. That's not really the kind of question that stackoverflow is for. There are many ways to solve any problem in programming, and many things come down to personal taste. We can't give you an objective answer to what the right approach is. There are other web sites where you can ask for people's opinions. – Håken Lid Sep 13 '17 at 21:46
  • @HåkenLid. Thanks for guiding me. I have removed the objective question, which was just one part of my original question. I hope the question is more clear now. Its more related to how to address POST method reloading the page, instead of sowing the results on flipside. – Addy Sep 14 '17 at 19:23

0 Answers0