How to Build a Quiz App with Django and QuizAPI
Step-by-step guide to building a quiz application with Django using the QuizAPI REST API. Fetch questions, render a quiz UI, and submit scores.
Overview
In this tutorial, you'll build a Django quiz application that pulls questions from QuizAPI and lets users take quizzes directly in your Django app. By the end, you'll have a working quiz page that fetches questions, tracks answers, and submits scores.
Prerequisites
- Python 3.10+
- Django 5.x installed
- A QuizAPI account and API key (get one free at quizapi.io)
- Basic familiarity with Django views and templates
Project Setup
Create a new Django project and app:
django-admin startproject quizproject
cd quizproject
python manage.py startapp quizzes
pip install requests
Add quizzes to INSTALLED_APPS in settings.py, and add your API key:
# settings.py
QUIZAPI_KEY = "your-api-key-here"
QUIZAPI_BASE_URL = "https://quizapi.io/api/v1"
Fetching Quizzes from the API
Create a service layer to talk to QuizAPI:
# quizzes/services.py
import requests
from django.conf import settings
def get_quizzes(limit=10, category=None):
"""Fetch published quizzes from QuizAPI."""
params = {"limit": limit}
if category:
params["category"] = category
response = requests.get(
f"{settings.QUIZAPI_BASE_URL}/quizzes",
headers={"Authorization": f"Bearer {settings.QUIZAPI_KEY}"},
params=params,
)
response.raise_for_status()
return response.json()["data"]
def get_quiz_questions(quiz_id):
"""Fetch questions for a specific quiz."""
response = requests.get(
f"{settings.QUIZAPI_BASE_URL}/questions",
headers={"Authorization": f"Bearer {settings.QUIZAPI_KEY}"},
params={"quizId": quiz_id},
)
response.raise_for_status()
return response.json()["data"]
Building the Views
# quizzes/views.py
from django.shortcuts import render
from .services import get_quizzes, get_quiz_questions
def quiz_list(request):
quizzes = get_quizzes(limit=20)
return render(request, "quizzes/list.html", {"quizzes": quizzes})
def quiz_play(request, quiz_id):
questions = get_quiz_questions(quiz_id)
return render(request, "quizzes/play.html", {
"quiz_id": quiz_id,
"questions": questions,
})
def quiz_results(request):
if request.method != "POST":
return render(request, "quizzes/results.html", {"score": 0, "total": 0})
# Calculate score from submitted answers
score = 0
total = 0
for key, value in request.POST.items():
if key.startswith("question_"):
total += 1
# value is the answer ID, check if it matches the correct answer
correct = request.POST.get(f"correct_{key}", "")
if value == correct:
score += 1
percentage = round((score / total) * 100) if total > 0 else 0
return render(request, "quizzes/results.html", {
"score": score,
"total": total,
"percentage": percentage,
})
Creating the Templates
Quiz List
<!-- templates/quizzes/list.html -->
{% extends "base.html" %}
{% block content %}
<h1>Available Quizzes</h1>
<div class="quiz-grid">
{% for quiz in quizzes %}
<div class="quiz-card">
<h2>{{ quiz.title }}</h2>
<p>{{ quiz.description }}</p>
<span class="badge">{{ quiz.difficulty }}</span>
<span class="badge">{{ quiz.questionCount }} questions</span>
<a href="{% url 'quiz_play' quiz.id %}" class="btn">Play Quiz</a>
</div>
{% endfor %}
</div>
{% endblock %}
Quiz Play
<!-- templates/quizzes/play.html -->
{% extends "base.html" %}
{% block content %}
<form method="post" action="{% url 'quiz_results' %}">
{% csrf_token %}
{% for q in questions %}
<div class="question-card">
<h3>{{ forloop.counter }}. {{ q.text }}</h3>
{% for answer in q.answers %}
<label class="answer-option">
<input type="radio"
name="question_{{ q.id }}"
value="{{ answer.id }}"
required>
{{ answer.text }}
</label>
{% endfor %}
<!-- Store correct answer ID in a hidden field -->
{% for answer in q.answers %}
{% if answer.isCorrect %}
<input type="hidden"
name="correct_question_{{ q.id }}"
value="{{ answer.id }}">
{% endif %}
{% endfor %}
</div>
{% endfor %}
<button type="submit" class="btn">Submit Answers</button>
</form>
{% endblock %}
URL Configuration
# quizzes/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.quiz_list, name="quiz_list"),
path("play/<str:quiz_id>/", views.quiz_play, name="quiz_play"),
path("results/", views.quiz_results, name="quiz_results"),
]
# quizproject/urls.py
from django.urls import path, include
urlpatterns = [
path("quizzes/", include("quizzes.urls")),
]
Running the App
python manage.py runserver
Visit http://localhost:8000/quizzes/ to see your quiz list. Click any quiz to play it, and submit your answers to see your score.
Next Steps
- Add user authentication to save scores per user
- Cache API responses with Django's cache framework to reduce API calls
- Add category filtering to the quiz list
- Style with Tailwind CSS or Bootstrap for a polished look
- Use the QuizAPI leaderboard endpoint to show high scores
Resources
Stay Updated
Get the latest tutorials and API tips delivered to your inbox.
No spam, unsubscribe anytime.
Related Articles
Building a Quiz Component in React with QuizAPI
Build a reusable React quiz component that fetches questions from QuizAPI, manages quiz state, and displays scores. Full TypeScript implementation included.
Building a Quiz Leaderboard with Real-Time Updates
Build a live quiz leaderboard with ranking algorithms, efficient data models, and real-time delivery using SSE and WebSockets.
Add Quizzes to Your Laravel App with QuizAPI
Integrate QuizAPI into a Laravel application with the HTTP client, Blade templates, and proper form handling for a complete quiz experience.
Enjoyed this article?
Share it with your team or try our quiz platform.