Designing a Quiz App with Django: From Concept to Completion

Introduction

We'll build the Django Quiz Application in this article. In general, The Django Quiz App is an adaptable and dynamic online tool created to transform education and evaluation. It was developed to meet the demand for dynamic and interesting online tests and provides schools, companies, and individuals with an easy-to-use platform to design, administer, and administer tests on a range of topics. With the help of this software, traditional ways of learning and testing will be transformed into something more efficient, fun, and supportive of lifelong learning.

Setting Up the Django Project

To begin, ensure that you have Python and Django installed on your system. You can install Django using pip, the Python package manager. Once installed, create a new Django project by running the following command:

django-admin startproject quiz

Next, navigate to the project directory and create a new Django app -

cd quiz
python manage.py startapp home

Now add this app to the ‘settings.py’

File Structure

File Structure

Then, we register our app in the settings.py file in the installed_apps sections shown below.

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "home",
    "django_extensions",
]

Setting up necessary Files


models.py

The code defines Django models for a quiz application. It includes models for categories, questions, and answers, along with a common base model for shared fields like timestamps. These models are used to organize and store quiz-related data in a Django project.

from django.db import models
import uuid
import random
# Create your models here.

class BaseModel(models.Model):
    uid=models.UUIDField(primary_key=True,default=uuid.uuid4,editable=False)
    created_at=models.DateField(auto_now_add=True)
    updated_at= models.DateField(auto_now_add=True)

    class Meta:
        abstract=True

class Category(BaseModel):
    category_name=models.CharField(max_length=100)

    def __str__(self) -> str:
        return self.category_name

class Question(BaseModel):
    category=models.ForeignKey(Category, related_name='category',on_delete=models.CASCADE)
    question=models.CharField(max_length=100)
    marks=models.IntegerField(default=5)

    def __str__(self) -> str:
        return self.question
    
    def get_answers(self):
        answer_objs=list(Answer.objects.filter(question = self))
        random.shuffle(answer_objs)
        data=[]

        for answer_obj in answer_objs:
            data.append({
                'answer' : answer_obj.answer,
                'is_correct' : answer_obj.is_correct
            })

        return data

class Answer(BaseModel):
    question=models.ForeignKey(Question, related_name='question_answer',on_delete=models.CASCADE)
    answer=models.CharField(max_length=100)
    is_correct=models.BooleanField(default=False)
    
    def __str__(self) -> str:
        return self.answer
  • The BaseModel serves as a foundation for our other models, defining common fields such as uid (a universally unique identifier), created_at, and updated_at. By setting abstract=True, we indicate that this model should not be directly instantiated but serves as a blueprint for other models to inherit from.
  • The Category model represents different categories or topics for our quiz questions. It contains a field category_name to store the name of the category. The __str__ method is overridden to provide a human-readable representation of the category.
  • The Question model represents individual questions in our quiz. It includes fields for the question itself, its associated category, and the marks allotted to it. Additionally, it provides a method get_answers() to fetch answers related to this question. This method shuffles the answers to ensure randomness and returns a list of answer objects along with their correctness status.
  • The Answer model stores possible answers to quiz questions. It maintains a reference to the associated question (question) and stores the answer text (answer). The is_correct field indicates whether the answer is correct or not. The __str__ method returns the answer text for readability.

Run these commands to apply the migrations.

python3 manage.py makemigrations
python3 manage.py migrate

views.py

The code is a part of a Django web application for quizzes.

  • home Function: Displays a list of quiz categories. Redirects to the quiz page for a selected category.
  • quiz Function: Displays a quiz page for a specific category.
  • get_quiz Function: Retrieves random quiz questions, optionally filtered by category. Returns them as JSON. Handles exceptions with a “Something went wrong” response.
    from django.http import HttpResponse, JsonResponse
    from django.shortcuts import render,redirect
    from .models import *
    import random
    # Create your views here.
    
    def home(request):
        context= {'categories': Category.objects.all()}
        if request.GET.get('category'):
            return redirect(f"/quiz/?category={request.GET.get('category')}")
        return render(request,"home.html",context)
    
    def quiz(request):
        context={'category': request.GET.get('category')}
        return render(request, 'quiz.html',context) 
    
    def get_quiz(request):
        try:
            question_objs= Question.objects.all()
            if request.GET.get('category'):
                question_objs=question_objs.filter(category__category_name__icontains=request.GET.get('category'))
            question_objs=list(question_objs)
            data=[]
            random.shuffle(question_objs)
            
    
            for question_obj in question_objs:
                data.append({
                    "uid" : question_obj.uid,
                    "category" : question_obj.category.category_name,
                    "question" : question_obj.question,
                    "marks" : question_obj.marks,
                    "answers" : question_obj.get_answers()
                })
    
            payload={'status' : True, 'data' : data}
    
            return JsonResponse(payload)
    
        except Exception as e:
            print(e)
        return HttpResponse("Something went wrong")
    
  • The home view retrieves all available categories from the database and passes them as context to the template home.html. If a category parameter is present in the request's query string, the view redirects the user to the /quiz/ URL with the selected category. Otherwise, it renders the home page template.
  • The quiz view renders the quiz page template (quiz.html). It retrieves the selected category from the query string parameters and passes it as context to the template. This view is responsible for displaying the quiz interface to the user.
  • The get_quiz view is responsible for retrieving quiz questions from the database and returning them as JSON data. It first fetches all questions and filters them based on the selected category (if provided). The questions are then randomized using random. shuffle() to ensure variety. For each question, relevant information including UID, category, question text, marks, and answers is collected into a dictionary and added to the data list. Finally, a JSON response containing the quiz data is returned to the client.

admin.py

Here we are registering the models.

from django.contrib import admin
from .models import *

# Register your models here.
admin.site.register(Category)

class AnswerAdmin(admin.StackedInline):
    model=Answer

class QuestionAdmin(admin.ModelAdmin):
    inlines=[AnswerAdmin]
admin.site.register(Question,QuestionAdmin)
admin.site.register(Answer)
  • In this section, we register the Category model with the Django admin interface. By doing so, Django automatically generates an admin interface for managing categories. Admin users can perform CRUD operations (Create, Read, Update, Delete) on categories directly from the admin panel.
  • Here, we define an inline model administration for answers within the question administration interface. The AnswerAdmin class is subclassed from admin.StackedInline specifies how answers should be displayed inline within the question editing page. We then create a QuestionAdmin class that specifies the inline relationship with AnswerAdmin. Finally, we register the Question model with the QuestionAdmin configuration, ensuring that questions are managed along with their associated answers in the admin interface.
  • Additionally, we directly register the Answer model with the Django admin interface. This registration allows admin users to manage answers independently if needed. However, in most cases, answers are managed inline within the question editing page as configured above
    Administration
    Add Question

Creating GUI


home.html

This HTML template is designed for a Django quiz app, providing a category selection form for users and using Bootstrap for styling and layout.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5 pt-5">
        <div class="col-md-6 mx-auto">
            <form method="get">
                <div class="form-group">
                    <label>Select Category</label>
                    <select name="category" class="form-control">
                        <option value="choose">Choose</option>
                        {% for category in categories %}
                        <option value="{{category.category_name}}">{{category.category_name}}</option>
                        {% endfor %}
                        img
                    </select>
                </div>
                <button class="btn btn-danger mt-3">Submit</button>
            </form>
        </div>
    </div>
</body>
</html>

quiz.html

This code integrates Vue.js into an HTML page to create a dynamic quiz interface where users can select answers, check correctness, and receive alerts. It fetches questions from a Django API based on the selected category.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>new</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">

</head>

<body>
    <div id="app">
        <div class="container mt-5 pt-5">
            <div class="col-md-6 mx-auto">
                <h3>Give Quiz</h3>
                <div v-for="question in questions">
                    <hr>
                    <p>[[question.question]]</p>
                    <div class="form-check" v-for="answer in question.answers">
                        <input @change="checkAnswer($event, question.uid)" :value="answer.answer"
                            class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
                        <label class="form-check-label" for="flexRadioDefault1">
                            [[answer.answer]]
                        </label>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

    <script>
        var app = new Vue({
            el: '#app',
            delimiters: ['[[', ']]'],
            data() {
                return {
                    category: "{{category}}",
                    questions: [],
                }
            },
            methods: {
                getQuestions() {
                    var _this = this
                    fetch(`/api/get-quiz?category=${_this.category}`)
                        .then(response => response.json())
                        .then(result => {
                            console.log(result)
                            _this.questions = result.data
                        })
                },
                checkAnswer(event, uid) {
                    this.questions.map(question => {
                        console.log(question.answers)
                        answers = question.answers
                        for (var i = 0; i < answers.length; i++) {
                            if (answers[i].answer == event.target.value) {
                                if (answers[i].is_correct) {
                                    console.log("Your answer is correct")
                                    alert("Hurry your answer is correct")
                                } else {
                                    console.log("your answer is wrong")
                                    alert("Sorry your answer is wrong")
                                }
                            }
                        }

                    })
                    console.log(event.target.value, uid)
                }
            },
            created() {
                this.getQuestions()
            },
        });

    </script>
</body>

</html>

quiz/urls.py

This is the urls.py file of our project quiz in this file we just map the other urls.py file of our home app for performing some operations.

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('', include('home.urls')),
    path('admin/', admin.site.urls),
]

home/urls.py

This is the urls.py file this is our app home urls.py.

from django.urls import path
from .import views
urlpatterns = [
    path('',views.home, name="home"),
    path('api/get-quiz',views.get_quiz, name="get_quiz"),
    path('quiz/',views.quiz, name="quiz")    
]

Deployment of the Project

Run the server with the help of the following command.

python3 manage.py runserver

Output

Submit

Select category

Give Quiz

If the selected answer is correct or incorrect alert like this will pop up.

Correct

Wrong

Conclusion

The Quiz Django app represents a sophisticated fusion of cutting-edge technologies aimed at providing users with an intuitive and stimulating quiz-taking experience. The Quiz Django application is a web-based platform crafted to facilitate the creation and management of quizzes. It merges Django, an influential Python web framework, with Vue.js, a JavaScript framework renowned for its capacity to construct dynamic user interfaces. The application enables users to.

  • Choose Categories: Users have the option to select quiz categories from a dropdown menu.
  • Respond to Questions: The application presents users with a collection of questions within their chosen category. Users can provide answers to these questions.
  • Validate Answers: After selecting an answer, the application verifies its accuracy and promptly provides feedback through notifications.
  • Dynamic User Interface: Vue.js is employed to develop an interactive user interface that dynamically updates in real time as users engage with the quiz.
  • Integration with API: The application retrieves quiz questions from a Django API based on the category selected by the user.

To sum up, the Quiz Django application combines the robust capabilities of Django for backend development with the interactive features of Vue.js for frontend user engagement, resulting in an immersive and educational quiz-taking platform.


Similar Articles