Site icon DataFlair

How to Create a Quiz Web Application with Python Django

create quiz web application python django

Python course with 57 real-time projects - Learn Python

We offer you a brighter future with FREE online courses - Start Now!!

Quiz – best way to check our knowledge on a particular topic.

We have visited a lot of quiz platforms lately, right! Ever wondered if you could develop one.

In this article, we will guide you to develop a quiz application using Python Django. Let’s see what all functionalities we will be developing in this project (for two roles – user and admin):

User:

Admin:

Project Prerequisites

You should have a basic knowledge of the following technologies:

To install Django:

pip install Django

Download Quiz App Python Code

Please download the source code of quiz web application: Quiz Web Application Python Code

Steps to Build Quiz App Project

1. Starting project:

Commands to start the project and app:

django-admin startproject DjangoQuiz
cd DjangoQuiz
django-admin startapp Quiz

2. Writing Models

Code:

from django.db import models
 
# Create your models here.
class QuesModel(models.Model):
    question = models.CharField(max_length=200,null=True)
    op1 = models.CharField(max_length=200,null=True)
    op2 = models.CharField(max_length=200,null=True)
    op3 = models.CharField(max_length=200,null=True)
    op4 = models.CharField(max_length=200,null=True)
    ans = models.CharField(max_length=200,null=True)
    
    def __str__(self):
        return self.question

We just need one model for this project, QuesModel.

Attributes of QuesModels:

The __str__() method returns a string representation of any object of QuesModel.

In Django when we use Sqlite3 database, we don’t have to write table definitions we just have to write models and after that, we have to run the following commands

Py manage.py makemigrations
Py manage.py migrate

3. forms.py

Code:

from django.forms import ModelForm
from .models import *
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
 
class createuserform(UserCreationForm):
    class Meta:
        model=User
        fields=['username','password'] 
 
class addQuestionform(ModelForm):
    class Meta:
        model=QuesModel
        fields="__all__"

To access, update, create or delete entries in the database (to implement CRUD functionality), we need forms.

Form makes it easy to implement CRUD functionality as we neither have to create forms to accept information from users nor we have to validate information manually, we can just use is_valid() method to validate the information before updating it in the database.

4. admin.py

Code:

from django.contrib import admin
from .models import *
 
# Register your models here.
admin.site.register(QuesModel)

Here, we are registering our model to the admin site, so that we can update or access the database from the admin panel also. But we need a superuser to access the admin site.

To create a staff (admin) user, run the below command

py manage.py createsuperuser

5. settings.py

To use javascript we have to specify the path of static files. Therefore, add the following code in settings.py

STATIC_URL = '/static/'
STATICFILES_DIRS=[BASE_DIR/'static']

6. urls.py

In this file we are just defining urls. To define urls:

Code:

"""DjangoQuiz URL Configuration
 
The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from Quiz.views import *
from django.conf import settings
from django.conf.urls.static import static
 
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home,name='home'),
    path('addQuestion/', addQuestion,name='addQuestion'),
    path('login/', loginPage,name='login'),
    path('logout/', logoutPage,name='logout'),
    path('register/', registerPage,name='register'),
 
]
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

7. views.py :

Code:

from django.shortcuts import redirect,render
from django.contrib.auth import login,logout,authenticate
from .forms import *
from .models import *
from django.http import HttpResponse
 
# Create your views here.
def home(request):
    if request.method == 'POST':
        print(request.POST)
        questions=QuesModel.objects.all()
        score=0
        wrong=0
        correct=0
        total=0
        for q in questions:
            total+=1
            print(request.POST.get(q.question))
            print(q.ans)
            print()
            if q.ans ==  request.POST.get(q.question):
                score+=10
                correct+=1
            else:
                wrong+=1
        percent = score/(total*10) *100
        context = {
            'score':score,
            'time': request.POST.get('timer'),
            'correct':correct,
            'wrong':wrong,
            'percent':percent,
            'total':total
        }
        return render(request,'Quiz/result.html',context)
    else:
        questions=QuesModel.objects.all()
        context = {
            'questions':questions
        }
        return render(request,'Quiz/home.html',context)
 
def addQuestion(request):    
    if request.user.is_staff:
        form=addQuestionform()
        if(request.method=='POST'):
            form=addQuestionform(request.POST)
            if(form.is_valid()):
                form.save()
                return redirect('/')
        context={'form':form}
        return render(request,'Quiz/addQuestion.html',context)
    else: 
        return redirect('home') 
 
def registerPage(request):
    if request.user.is_authenticated:
        return redirect('home') 
    else: 
        form = createuserform()
        if request.method=='POST':
            form = createuserform(request.POST)
            if form.is_valid() :
                user=form.save()
                return redirect('login')
        context={
            'form':form,
        }
        return render(request,'Quiz/register.html',context)
 
def loginPage(request):
    if request.user.is_authenticated:
        return redirect('home')
    else:
       if request.method=="POST":
        username=request.POST.get('username')
        password=request.POST.get('password')
        user=authenticate(request,username=username,password=password)
        if user is not None:
            login(request,user)
            return redirect('/')
       context={}
       return render(request,'Quiz/login.html',context)
 
def logoutPage(request):
    logout(request)
    return redirect('/')

View.py is the file which contains the main or we can say the business logic of the project as this file can only access the database and also it can pass the information to templates so that it can be displayed on the web browser.

Home

This is the most important view of our project as this method is responsible for displaying the quiz page as well as the result page.

For Quiz Page: It renders all the questions from QuesModel and then it just passes all the questions to home.html

For result page: It calculates the score by giving ten marks for every correct question and zero (i.e. no negative marking) for every incorrect question. And then it calculates the percentage score.

Finally, it sends all these calculated values along with time elapsed, number of correct answers, number of incorrect answers to result.html. Result.html displays all this information.

Add Question:

This method is only for admin, if any user tries to access this method, the user is redirected to the home page. We are basically using the add question form in this to create a form object.

To validate the information entered by the user we are using is_valid method and after validating the information we are adding another question in the database using save() method.

Result.html

{% extends 'Quiz/dependencies.html' %}
 
{% block content %}
 
<div class="container ">
        
    <div class="card-columns" style="padding: 10px; margin: 20px;">
        <div class="card" align="centre " style="width: 32rem; border:5px black solid">
            <img class="card-img-top" src="http://kmit.in/emagazine/wp-content/uploads/2018/02/karnataka-results.jpg" alt="Card image cap">
            <div class="card-body">
                <h5 class="card-title">Score: {{score}}</h5>
 
                <p class="card-text">Percentage: {{percent}}%</p>
                <p class="card-text">Time Taken: {{time}} seconds</p>
                <p class="card-text">Correct answers: {{correct}}</p>
                <p class="card-text">Incorrect answers: {{wrong}}</p>
                <p class="card-text">Total questions: {{total}}</p>
                <h5>All the best for next quiz!</h5>
            </div>
        </div>
    </div>
 
</div>
 
{% endblock %}

Result page:

Home.html

{% extends 'Quiz/dependencies.html' %}
 
{% block content %}
{% load static %}
<div class="container ">
<h1>Welcome to DataFlair Quiz</h1>
 
<div align="right " id="displaytimer"><b>Timer: 0 seconds</b></div>
 
 <form method='post' action=''>
    {% csrf_token %}
    {% for q  in questions%}
    <div class="form-group">
      <label for="question">{{q.question}}</label>
    </div>
    <div class="form-check">
        <div class="form-check">
            <input class="form-check-input" type="radio" name="{{q.question}}" id="gridRadios1" value="option1" checked>
            <label class="form-check-label" for="gridRadios1">
                {{q.op1}}
            </label>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="radio" name="{{q.question}}" id="gridRadios2" value="option2">
            <label class="form-check-label" for="gridRadios2">
                {{q.op2}}
            </label>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="radio" name="{{q.question}}" id="gridRadios1" value="option3">
            <label class="form-check-label" for="gridRadios1">
                {{q.op3}}
            </label>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="radio" name="{{q.question}}" id="gridRadios2" value="option4">
            <label class="form-check-label" for="gridRadios2">
                {{q.op4}}
            </label>
        </div>
        <br>
    </div>    
    {% endfor %}
    <input id='timer' type='hidden' name="timer" value="">
    <br>
    <button type="submit" class="btn btn-primary">Submit</button>
  </form>
    {% block script %}
        <script>
 
            console.log('hello world')
            const timer=document.getElementById('displaytimer')
            console.log(timer.textContent)
            const inputtag = document.getElementById('timer')
 
            t=0
            setInterval(()=>{
                t+=1
                timer.innerHTML ="<b>Timer: " +t+" seconds</b>"
                inputtag.value = t
            },1000)
        </script>
    {% endblock script %}
 
</div>
{% endblock %}

Quiz page

For admin, only the navigation bar is different, it has one button for adding questions.

Navbar.html

{% load static %}
 
<style>
  .greet{
    font-size: 18px;
    color: #fff;
    margin-right: 20px;
  }
</style>
 
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNav">
 
    <ul class="navbar-nav">
      
      <li class="nav-item active">
        <a class="nav-link" href="{% url 'home' %}">Home</a>
      </li>
      </li>
      <li class="nav-item active">
        
      {% if request.user.is_staff %}
      </li>
      <li class="nav-item active">
        <a class="nav-link" href="{% url 'addQuestion' %}">Add Question</a>
      </li>
      {% endif %} 
 
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{% url 'login' %}">Login</a>
      </li>
    </ul>
  </div>
 
  <span class="greet">Hello, {{request.user}}</span>
  <span ><a  class="greet" href="{% url 'logout' %}">Logout</a></span>
 
</nav>

AddQuestion.html

{% extends 'Quiz/dependencies.html' %}
 
{% block content %}
 
<div class="jumbotron container row">
    <div class="col-md-6">
        <h1>Add Question</h1>
        <div class="card card-body">
           <form action="" method="POST">
              {% csrf_token %}
                {{form.as_p}}
                <br>
             <input type="submit" name="Submit">
             </form>
            </div>
        </div>
    </div>
 
</div>
 
{% endblock %}
 

Add Question page

dependencies.html

{% load static %}
<html>
    <head>
        <title>
            DataFlair Online Quiz with Django
        </title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    </head>
    <body>        
        {% include 'Quiz/navbar.html' %}
        {% block content %}   
        {% endblock %}
        <br>
       
        <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
    </body>
</html>

Login.html

{% extends 'Quiz/dependencies.html' %}
{% load static%}
{% block content %}
<div class="container jumbotron">
    <form method="POST" action="">
        {% csrf_token %}
        <p><input type="text" name="username" placeholder="Username..."></p>
        <p><input type="password" name="password" placeholder="Password..." ></p>
        <input class="btn btn-success" type="submit" value="Login">
        <p>Do not have an account<a href='{% url 'register' %}'>Register</a></p>
    </form>
</div>
{% endblock %}

Register.html

{% extends 'Quiz/dependencies.html' %}
{% load static %}
{% block content %}
<div class="container jumbotron">
    <form method="POST" action="" >
        {% csrf_token %}
        {{form.as_p}}
       
        <input class="btn btn-success" type="submit" value="Register Account">
    </form>
</div>
{% endblock %}

Summary

We have developed an Online Quiz application Project using Python Django. We developed quiz web application with following functionalities: Login, Sign up, Add Question, Quiz Page, Result Page. You can develop more interesting projects with Django, so keep exploring and keep learning.

Exit mobile version