skip to Main Content

I have users take a quiz. After each question, I want to show them whether their answer was correct or incorrect. The correct answer should be highlighted in green, and their answer (if incorrect) should be highlighted in red (using Twitter Bootstrap styles).

I am currently rendering the quiz results page in Django and HTML like so:

{{ player.question }}
<div class="myradio">
    <label for="choice_1"><input id="id_1" type="radio" value="q1" disabled /> {{q1}}</label>
</div>
<div class="myradio">
    <label for="choice_2"><input id="id_2" type="radio" value="q2" disabled /> {{q2}}</label>
</div>
<div class="myradio">
    <label for="choice_3"><input id="id_3" type="radio" value="q3" disabled /> {{q3}}</label>
</div>
<div class="myradio">
    <label for="choice_4"><input id="id_4" type="radio" value="q4" disabled /> {{q4}}</label>
</div>


<p><b>Correct Answer: {{solution}}<b></p>

Total Score: {{total_score}}

I am storing the solution to the question in {{solution}}. I have been trying to figure out how to selectively apply CSS filters if, for example, {{q1}} == {{solution}} that should be highlighted green. I can grab the participant’s answer with {{player.submitted_answer}}, and so want to highlight a div element red if {{player.submitted_answer}} != {{solution}}.

I have tried messing around with if statement blocks, but can’t seem to get it right. Any ideas?

@cezar, a snippet of pages.py and models.py

In pages.py I have the following class

class Question(Page):
    timeout_seconds = 120

    template_name = 'quiz/Question.html'
    form_model = 'player'
    form_fields = ['submitted_answer', 'confidence']


    def submitted_answer_choices(self):
        qd = self.player.current_question()
        return [
            qd['choice1'],
            qd['choice2'],
            qd['choice3'],
            qd['choice4'],
        ]

    def confidence_error_message(self, value):

        if value == 50:
            return 'Please indicate your confidence in your answer.  It is important you answer accurately.'


    def before_next_page(self):
        self.player.check_correct()

In models.py, the relevant class is Player and Subsession:

class Player(BasePlayer):

trial_counter = models.IntegerField(initial=0)


question_id = models.IntegerField()
confidence = models.FloatField(widget=widgets.Slider(attrs={'step': '0.01'}))
confidence_private = models.FloatField(widget=widgets.Slider(attrs={'step': '0.01'}))

question = models.StringField()
solution = models.StringField()
submitted_answer = models.StringField(widget=widgets.RadioSelect)
submitted_answer_private = models.StringField(widget=widgets.RadioSelect)

is_correct = models.BooleanField()
total_score = models.IntegerField(initial = 0)

def other_player(self):
    return self.get_others_in_group()[0]

def current_question(self):
    return self.session.vars['questions'][self.round_number - 1]

def check_correct(self):
    self.is_correct = self.submitted_answer == self.solution

def check_partner_correspondence(self):
    self.submitted_answer == self.get_others_in_group()[0].submitted_answer

def check_partner_correct(self):
    self.get_others_in_group()[0].submitted_answer == self.solution

def check_if_awarded_points(self):
    self.get_others_in_group()[0].submitted_answer == self.submitted_answer == self.solution

def score_points(self):
    if self.get_others_in_group()[0].submitted_answer == self.submitted_answer == self.solution:
        self.total_score +=1
    else:
        self.total_score -=1


def set_payoff(self):
    if(self.check_if_awarded_points()):
        self.total_score +=1

class Subsession(BaseSubsession):

def creating_session(self):
    if self.round_number == 1:
        self.session.vars['questions'] = Constants.questions
        ## ALTERNATIVE DESIGN:
        ## to randomize the order of the questions, you could instead do:

        # import random
        # randomized_questions = random.sample(Constants.questions, len(Constants.questions))
        # self.session.vars['questions'] = randomized_questions

        ## and to randomize differently for each participant, you could use
        ## the random.sample technique, but assign into participant.vars
        ## instead of session.vars.

    for p in self.get_players():
        question_data = p.current_question()
        p.question_id = question_data['id']
        p.question = question_data['question']
        p.solution = question_data['solution']

3

Answers


  1. Chosen as BEST ANSWER

    I ended up solving my own problem:

    I am not sure what to do as Albar's answer helped the most.

      <div class={% if q1 == player.solution  %} "green" {% else %} "red" {% endif %}>
           <input type="radio" disabled/> {{q1}}</label>
       </div>
    
       <div class={% if q2 == player.solution  %} "green" {% else %} "red" {% endif %}>
            <input type="radio" disabled /> {{q2}}
        </div>
    
       <div class={% if q3 == player.solution  %} "green" {% else %} "red" {% endif %}>
            <input type="radio" disabled /> {{q3}}
        </div>
    
       <div class={% if q4 == player.solution %} "green" {% else %} "red" {% endif %}>
            <input type="radio" disabled /> {{q4}}
        </div>
    

    And then the CSS:

    <style>
    
    
    .green {
      color: #00FF00; 
    }
    
    .red {
      color: red; 
    }
    
    </style>
    

  2. I agree with @Sapna-Sharma and @albar comment.

    You may use a simple CSS class to set the color to green and use a {% if [...] %} template filter to add the the CSS class only to the good answer

    You may refer to Django official documentation to know how to handle template filter.

    Login or Signup to reply.
  3. You can accmoplish this with some CSS and minimal templating.

    Consider the following HTML template

    The key here is class="answer{% if answer == solution %} solution{% endif %}"

    <h2>{{ question }}</h2>
    <form>
    {% for answer in answers %}
        <label for="answer{{ forloop.counter }}">{{ answer }}</label>
        <input id="answer{{ forloop.counter }}" type="radio" name="answer" class="answer{% if answer == solution %} solution{% endif %}" value="{{ answer }}">
        <br/>
    {% endfor %}
    
    <p class="result incorrect">Sorry, that was not correct. The solution was {{ solution }}</p>
    <p class="result correct">Correct! Answer: {{ solution }}</p>
    </form>
    

    With the Following CSS

    .result {
        display: none;
    }
    .answer:checked ~ .result.incorrect{
        display: block;
        color: red;
    }
    .answer.solution:checked ~ p.result.correct {
        display: block;
        color: green;
    }
    
    .answer.solution:checked ~ p.result.incorrect {
        display: none;
    }
    

    And the following route

    def quiz(request):
        question = "What is 2 + 2?"
        solution = "4"
        answers = [solution, "22", "NaN", "0"]
        random.shuffle(answers)
        return render(request, 'foobar/quiz.html', context=locals())
    

    You would get a result like this jsfiddle

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search