0

I currently use Django 3.1.2 and Python 3.7. I have a problem with creating the quiz below.

Here's my code:

views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader


from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from .models import Question
from .models import Answer
#from .models import Answer 

# Create your views here.

def index(request):
    return render(request, 'apquiz/index.html')
    #print(request.POST)

def question(request):
    template = loader.get_template('apquiz/hi.html')
    #questions = ["1. What is Dosie's position in PURPLE KISS?", "2. Yuki's position in PURPLE KISS, based on this excerpt is:","3. PURPLE KISS has how many members:","4. PURPLE KISS debuted on","5. Which of the following is PURPLE KISS's main vocalist?"]
    #answers = [{'a. main rapper, main dancer, vocalist':0,'b. lead dancer, lead rapper':0, 'c. main dancer, vocalist':1,'d. main dancer, lead rapper':0},{'a. lead dancer, vocalist, rapper, visual':0,'b. lead rapper, lead dancer, vocalist, visual':0, 'main rapper, lead dancer, vocalist, visual':1, 'd. main vocalist, lead dancer, rapper, visual':0},{'a. 7':1,'b. 2':0,'c.9':0,'d.2':0},  {'a. August 3, 2020':0,'b. March 15, 2021':1, 'c. February 3, 2021':0,'d. November 26, 2020':0},{'a. Yuki':0,'b. Dosie':0,'c. Jieun':0,'d. Swan':1}]  
    #questions = Question.objects.get()
    #answers = Answer.objects.get()
    question_set=Question.objects.all()
    answer_set=Answer.objects.all()
    context = {}
    numberofquestions = len(question_set)
    numberofanswers = len(answer_set)
    numberofcorrectanswers = 0
    for i in question_set:
        for j in answers:
            if i == j:
                #context[i] = j #mke sure questions correspond to answrs
                context['questions'] = question_set
            if j.values == 1: #select the correct answer
                numberofcorrectanswers += 1
    percent = (numberofcorrectanswers/numberofquestions) * 100
    if percent >= 25 and percent <= 50:
        score = 2
    elif percent > 50 and percent < 75:
        score = 3
    elif percent >= 75 and percent < 90:
        score = 4
    elif percent >= 90:
        score = 5
    else:
        score = 1
    response = "You are on track to get a" + str(score) + "on an exam like this."
    return render(request, "apquiz/hi.html", context)

models.py

from django.db import models
import random
from jsonfield import JSONField


# Create your models here.
def question():
    return ["1. What is Dosie's position in PURPLE KISS?", "2. Yuki's position in PURPLE KISS, based on this excerpt is:","3. PURPLE KISS has how many members:","4. PURPLE KISS debuted on","5. Which of the following is PURPLE KISS's main vocalist?"]

def answer():
    return {'a. main rapper, main dancer, vocalist':0,'b. lead dancer, lead rapper':0, 'c. main dancer, vocalist':1,'d. main dancer, lead rapper':0},{'a. lead dancer, vocalist, rapper, visual':0,'b. lead rapper, lead dancer, vocalist, visual':0, 'main rapper, lead dancer, vocalist, visual':1, 'd. main vocalist, lead dancer, rapper, visual':0},{'a. 7':1,'b. 2':0,'c.9':0,'d.2':0},  {'a. August 3, 2020':0,'b. March 15, 2021':1, 'c. February 3, 2021':0,'d. November 26, 2020':0},{'a. Yuki':0,'b. Dosie':0,'c. Jieun':0,'d. Swan':1}


class Question(models.Model):
    question_text = models.CharField(max_length=255,default=question)
    #question_text = ["1. What is Dosie's position in PURPLE KISS?", "2. Yuki's position in PURPLE KISS, based on this excerpt is:","3. PURPLE KISS has how many members:","4. PURPLE KISS debuted on","5. Which of the following is PURPLE KISS's main vocalist?"]
    #created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.question_text

    #correct answer

class Answer(models.Model):
    answer_text = JSONField(default=answer)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    def __str__(self):
        return self.answer_text

urls.py

from django.contrib import admin
from django.urls import include, path
from . import views
from django.conf import settings
#from django.conf.urls.static import static

app_name= 'apquiz'

urlpatterns = [
    path('admin/', admin.site.urls),
    path('quiz/', views.question, name = 'quiz'),
]

hi.html

<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="" method="post">
{% csrf_token %}
{% for question in questions %} 
    <input type="radio" name="choice" id="choice{{ forloop.counter0 }}" value="{{ choice.id }}">
    <label for="answer{{ forloop.counter }}">{{ answer }}</label><br>
{% endfor %}
<input type="submit" value="Submit Quiz">
<h1>{{ question }}</h1>

<ul>
{% for choice in question.choice_set.all %}
    <li>{{ answer }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

</form>

Those are the pages I worked most with. If anyone could help me fix these files, that would be appreciated. I am trying to make a quiz with multiple choice answers without having to edit using admin file (meaning it is already given and you cannot change them in the administration site), and in order to edit these questions, you have to edit the code yourself. As of now, I only see an answer button which returns nothing. I need it to return a score from 1 to 5 (I am trying to make a parody of an Ap Exam). If anyone could help me with this code or let me know any errors, this would be very much appreciated. My HTML skills are not very good, and I especially need help with that part, like I don't know how to display them properly.

  • It seems that `context` does not contain any `QuerySet` or `object`. Try adding `question_set=Question.objects.all()` to `context['questions'] = question_set`. At your template you can loop `{% for question in questions %}` and maybe at the next step you can loop `{% for choice in question.choice_set.all %}` – Klim Bim Jun 02 '21 at 05:19
  • Here you can find a similar approach [nested loop](https://stackoverflow.com/questions/13232320/nested-loop-in-django-template) – Klim Bim Jun 02 '21 at 05:37
  • I recommend storing each question. At this point you don´t have stored data. For instance, `question_text = models.CharField(max_length=255)` at your `Question`-model and `answer_text = JSONField()` at your `Answer`-model. After that you can establish a OneToMany relationship between `Question` and `Answer`. However, for me the `Answer`-model is little bit unusual. – Klim Bim Jun 02 '21 at 05:50
  • @KlimBim updated the Code but for some reason cannot migrate it. – Vladimir George Jun 02 '21 at 21:39
  • For some reason I get an error which is '`OperationalError at /quiz/ no such column: apquiz_question.question_text` at line 28, in question at `views.py` – Vladimir George Jun 02 '21 at 21:47
  • Do you have the opportunity to reset your db and create a new one? – Klim Bim Jun 07 '21 at 09:43

1 Answers1

0

I adjusted your code a little bit. I hope this gives you a starting point.

models.py

class Question(models.Model):
    question_text = models.CharField(max_length=255)
    correct_answer = models.CharField(max_length=255)

    def __str__(self):
        return self.question_text

class Answer(models.Model):
    answer_text = models.CharField(max_length=255)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)

    def __str__(self):
        return self.answer_text

admin.py

Add your Question and Answer via admin-panel and create a relationships to each Question

admin.site.register(Question)
admin.site.register(Answer)

hi.html

<form action="" method="post">
{% csrf_token %}
{% for question in questions %}
  <h1>{{ question.question_text }}</h1>
  {% for answer in question.answer_set.all %}
    <input type="radio" name={{ question.pk }} value="{{ answer.answer_text }}">
    <label for="answer{{ forloop.counter }}">{{ answer }}</label><br>
  {% endfor %}
{% endfor %}
<input type="submit" value="Submit Quiz">
<h1>Your score is {{ score }}/{{ questions.count }}</h1>
</form>

views.py

def question(request):
    questions = Question.objects.all()
    context = {'questions': questions, 'score': 0}

    if request.method == 'GET':
        return render(request, "apquiz/hi.html", context)
    elif request.method == 'POST':
        data = request.POST.copy()
        data.pop('csrfmiddlewaretoken')  #  remove key bc at Question.objects.get(pk='csrfmiddlewaretoken') won´t be found
        score = 0
        for key, value in data.items():  # key is primary key of name={{ question.pk }} in your "hi.html", value contains your choosen answer 
            if Question.objects.get(pk=key).correct_answer == value:
                score += 1
        context['score'] = score
        return render(request, "apquiz/hi.html", context)
Klim Bim
  • 484
  • 2
  • 7