Skip to content

Commit a5a3ba5

Browse files
committed
final
1 parent 2fa2f71 commit a5a3ba5

37 files changed

+1095
-24
lines changed

core/settings.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,18 @@
3131
# Application definition
3232

3333
INSTALLED_APPS = [
34+
# internal apps
35+
"quiz",
3436
"django.contrib.admin",
3537
"django.contrib.auth",
3638
"django.contrib.contenttypes",
3739
"django.contrib.sessions",
3840
"django.contrib.messages",
3941
"django.contrib.staticfiles",
40-
# internal apps
41-
"quiz",
42+
'crispy_forms',
43+
'widget_tweaks',
44+
45+
4246
]
4347

4448
MIDDLEWARE = [
@@ -127,3 +131,7 @@
127131

128132
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
129133
AUTH_USER_MODEL = "quiz.User"
134+
135+
LOGIN_URL = "quiz:login"
136+
LOGOUT_REDIRECT_URL = "quiz:logout"
137+
LOGIN_REDIRECT_URL = "quiz:home"

quiz/admin.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from django.contrib import admin
2-
from .models import User, Quiz, Question, Option, Subject
2+
from django.contrib.auth.admin import UserAdmin
3+
4+
from .models import User, Quiz, Question, Option, Subject, Result
35

46

57
class BaseTabularInline(admin.TabularInline):
@@ -21,7 +23,7 @@ class OptionInline(BaseTabularInline):
2123

2224

2325
@admin.register(User)
24-
class UserAdmin(admin.ModelAdmin):
26+
class UserAdmin(UserAdmin):
2527
list_display = ["get_full_name", "username", "email"]
2628
search_fields = ("first_name", "last_name", "email", "username")
2729

@@ -59,3 +61,7 @@ class QuestionAdmin(admin.ModelAdmin):
5961
class OptionAdmin(admin.ModelAdmin):
6062
list_display = ["name", "is_correct"]
6163
search_fields = ("name",)
64+
65+
@admin.register(Result)
66+
class ResultAdmin(admin.ModelAdmin):
67+
list_display = ['id', 'by', 'score', 'quiz']

quiz/forms.py

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from django import forms
2+
from .models import User, Quiz
3+
from django.contrib.auth.forms import UserCreationForm
4+
5+
6+
class UserForm(UserCreationForm):
7+
class Meta:
8+
model = User
9+
fields = (
10+
"first_name",
11+
"username",
12+
"password1",
13+
"password2",
14+
)
15+
16+
def __init__(self, *args, **kwargs):
17+
super(UserForm, self).__init__(*args, **kwargs)
18+
for field in ["username", "password1", "password2"]:
19+
self.fields[field].help_text = None
20+
self.fields['first_name'].label = 'Name'
21+
self.fields['first_name'].required = True
22+
23+
class QuizForm(forms.ModelForm):
24+
class Meta:
25+
model = Quiz
26+
exclude = ['authored_by',]
27+
def __init__(self, *args, **kwargs):
28+
super(QuizForm, self).__init__(*args, **kwargs)
29+
self.fields['title'].label = ''
30+
title = forms.CharField(widget=forms.TextInput(attrs={'class': 'special special_big', 'placeholder':'Quiz Title'}))
31+
32+
33+
class QuestionForm(forms.Form):
34+
quiz = forms.UUIDField(widget=forms.HiddenInput())
35+
question = forms.CharField(label='', widget=forms.TextInput(attrs={'class': 'special', 'placeholder':'Question'}))
36+
option_1 = forms.CharField(label='', widget=forms.TextInput(attrs={'class': 'special special_small', 'placeholder':'Option A'}))
37+
option_2 = forms.CharField(label='', widget=forms.TextInput(attrs={'class': 'special special_small', 'placeholder':'Option B'}))
38+
option_3 = forms.CharField(label='', widget=forms.TextInput(attrs={'class': 'special special_small', 'placeholder':'Option C'}))
39+
correct_answer = forms.ChoiceField(choices=[(1, 'A'), (2, 'B'), (3, 'C')], widget=forms.RadioSelect(attrs={'class':'radio-inline', 'required':True}))
40+
41+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Generated by Django 4.1.5 on 2023-01-24 19:23
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("quiz", "0002_subject_quiz_question_option"),
10+
]
11+
12+
operations = [
13+
migrations.AlterModelOptions(
14+
name="option",
15+
options={"verbose_name": "Option", "verbose_name_plural": "Options"},
16+
),
17+
migrations.AlterModelOptions(
18+
name="question",
19+
options={"verbose_name": "Question", "verbose_name_plural": "Questions"},
20+
),
21+
migrations.AlterModelOptions(
22+
name="quiz",
23+
options={
24+
"ordering": ("-authored_on",),
25+
"verbose_name": "Quiz",
26+
"verbose_name_plural": "Quizzes",
27+
},
28+
),
29+
migrations.AlterModelOptions(
30+
name="subject",
31+
options={
32+
"ordering": ("name",),
33+
"verbose_name": "Subject",
34+
"verbose_name_plural": "Subjects",
35+
},
36+
),
37+
migrations.AlterModelOptions(
38+
name="user",
39+
options={"verbose_name": "User", "verbose_name_plural": "Users"},
40+
),
41+
migrations.AddField(
42+
model_name="quiz",
43+
name="title",
44+
field=models.CharField(blank=True, max_length=200, null=True),
45+
),
46+
]

quiz/migrations/0004_result.py

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Generated by Django 4.1.5 on 2023-02-08 07:18
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
("quiz", "0003_alter_option_options_alter_question_options_and_more"),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name="Result",
17+
fields=[
18+
(
19+
"id",
20+
models.BigAutoField(
21+
auto_created=True,
22+
primary_key=True,
23+
serialize=False,
24+
verbose_name="ID",
25+
),
26+
),
27+
("score", models.PositiveIntegerField()),
28+
("created_at", models.DateField(auto_now_add=True)),
29+
(
30+
"by",
31+
models.ForeignKey(
32+
on_delete=django.db.models.deletion.CASCADE,
33+
to=settings.AUTH_USER_MODEL,
34+
),
35+
),
36+
(
37+
"quiz",
38+
models.ForeignKey(
39+
on_delete=django.db.models.deletion.CASCADE, to="quiz.quiz"
40+
),
41+
),
42+
],
43+
options={
44+
"verbose_name": "Result",
45+
"verbose_name_plural": "Results",
46+
},
47+
),
48+
]

quiz/models.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ class Meta:
2626

2727
class Quiz(models.Model):
2828
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
29+
title = models.CharField(max_length=200 ,blank=True, null=True)
2930
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
3031
authored_on = models.DateTimeField(auto_now=True)
3132
authored_by = models.ForeignKey(User, on_delete=models.CASCADE)
3233
is_private = models.BooleanField(default=False)
3334

3435
def __str__(self):
35-
return str(self.id)
36+
return str(self.title)
3637

3738
class Meta:
3839
ordering = ("-authored_on",)
@@ -63,3 +64,14 @@ def __str__(self):
6364
class Meta:
6465
verbose_name = "Option"
6566
verbose_name_plural = "Options"
67+
68+
class Result(models.Model):
69+
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
70+
by = models.ForeignKey(User, on_delete=models.CASCADE)
71+
score = models.PositiveIntegerField()
72+
created_at = models.DateField(auto_now_add=True)
73+
74+
class Meta:
75+
verbose_name = 'Result'
76+
verbose_name_plural = 'Results'
77+

quiz/templates/base.html

+9-4
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,25 @@
66
<meta charset="UTF-8">
77
<meta http-equiv="X-UA-Compatible" content="IE=edge">
88
<meta name="viewport" content="width=device-width, initial-scale=1.0">
9+
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
10+
<script src="{% static 'bootstrap.min.js' %}"></script>
11+
<link rel="stylesheet" href="{% static 'style.css' %}">
912
<script src="{% static 'htmx.min.js' %}"></script>
1013
<title>{% block title %}
1114

1215
{% endblock title %}</title>
1316
</head>
14-
<header>this is header</header>
1517

1618
<body>
19+
{% include 'nav.html' %}
1720
{% block content %}
1821

1922
{% endblock content %}
2023
</body>
21-
<footer>
22-
this is footer
23-
</footer>
2424

25+
{% comment %}
26+
<footer class="fs-5 fixed-bottom text-center p-3 fw-bold container-fluid" style="background-color: #ff8142ab;">
27+
Made by Vivek! Trust Me
28+
</footer>
29+
{% endcomment %}
2530
</html>

quiz/templates/nav.html

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{% load static %}
2+
{% if request.user.is_authenticated %}
3+
<nav class="navbar" style="background-color:#f2edd9">
4+
<div class="container-fluid ">
5+
<a class="navbar-brand column-gap-3 d-flex align-items-center" href="/">
6+
<img src="{% static 'images/logo.png' %}" alt="Logo" width="64"
7+
class="d-inline-block align-text-top">
8+
<span class="nav_text"> Quizter</span>
9+
</a>
10+
<span class="navbar-brand mb-0 h1 text-center" style="display: flex;gap: 2em;">
11+
12+
<a href="{% url 'quiz:logout' %}">
13+
14+
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="#ff8042" class="bi bi-door-open-fill"
15+
viewBox="0 0 16 16">
16+
<path
17+
d="M1.5 15a.5.5 0 0 0 0 1h13a.5.5 0 0 0 0-1H13V2.5A1.5 1.5 0 0 0 11.5 1H11V.5a.5.5 0 0 0-.57-.495l-7 1A.5.5 0 0 0 3 1.5V15H1.5zM11 2h.5a.5.5 0 0 1 .5.5V15h-1V2zm-2.5 8c-.276 0-.5-.448-.5-1s.224-1 .5-1 .5.448.5 1-.224 1-.5 1z" />
18+
</svg>
19+
<div class="name text-muted text-decoration-none text-center pt-1">Log Out</div>
20+
</a>
21+
<a href="{% url 'quiz:contact' %}">
22+
23+
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="#ff8042" class="bi bi-envelope-check-fill"
24+
viewBox="0 0 16 16">
25+
<path
26+
d="M.05 3.555A2 2 0 0 1 2 2h12a2 2 0 0 1 1.95 1.555L8 8.414.05 3.555ZM0 4.697v7.104l5.803-3.558L0 4.697ZM6.761 8.83l-6.57 4.026A2 2 0 0 0 2 14h6.256A4.493 4.493 0 0 1 8 12.5a4.49 4.49 0 0 1 1.606-3.446l-.367-.225L8 9.586l-1.239-.757ZM16 4.697v4.974A4.491 4.491 0 0 0 12.5 8a4.49 4.49 0 0 0-1.965.45l-.338-.207L16 4.697Z" />
27+
<path
28+
d="M16 12.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Zm-1.993-1.679a.5.5 0 0 0-.686.172l-1.17 1.95-.547-.547a.5.5 0 0 0-.708.708l.774.773a.75.75 0 0 0 1.174-.144l1.335-2.226a.5.5 0 0 0-.172-.686Z" />
29+
</svg>
30+
<div class="name text-muted text-decoration-none text-center pt-1">Contact Us</div>
31+
</a>
32+
</a>
33+
<a href="{% url 'quiz:about' %}">
34+
35+
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="#ff8042" class="bi bi-book-half"
36+
viewBox="0 0 16 16">
37+
<path
38+
d="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" />
39+
</svg>
40+
<div class="name text-muted text-decoration-none text-center pt-1">About Us</div>
41+
</a>
42+
</span>
43+
44+
45+
</div>
46+
</nav>
47+
{% else %}
48+
<nav class="navbar ">
49+
<div class="container-fluid align-right justify-content-end">
50+
51+
<span class="navbar-brand mb-0 h1 text-center" style="display: flex;gap: 2em;">
52+
{% if request.path == '/signup/'%}
53+
<a href="{% url 'quiz:login' %}">
54+
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="#ff8042" class="bi bi-arrow-left-square-fill"
55+
viewBox="0 0 16 16">
56+
<path
57+
d="M16 14a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12zm-4.5-6.5H5.707l2.147-2.146a.5.5 0 1 0-.708-.708l-3 3a.5.5 0 0 0 0 .708l3 3a.5.5 0 0 0 .708-.708L5.707 8.5H11.5a.5.5 0 0 0 0-1z" />
58+
</svg>
59+
<div class="name text-muted text-decoration-none text-center px-3 py-1">Log In</div>
60+
</a>
61+
{% else %}
62+
63+
<a href="{% url 'quiz:signup' %}">
64+
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="#ff8042" class="bi bi-plus-square-fill"
65+
viewBox="0 0 16 16">
66+
<path
67+
d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z" />
68+
</svg>
69+
<div class="name text-muted text-decoration-none text-center px-3 py-1">Sign Up</div>
70+
</a>
71+
{% endif %}
72+
<a href="{% url 'quiz:contact' %}">
73+
74+
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="#ff8042" class="bi bi-envelope-check-fill"
75+
viewBox="0 0 16 16">
76+
<path
77+
d="M.05 3.555A2 2 0 0 1 2 2h12a2 2 0 0 1 1.95 1.555L8 8.414.05 3.555ZM0 4.697v7.104l5.803-3.558L0 4.697ZM6.761 8.83l-6.57 4.026A2 2 0 0 0 2 14h6.256A4.493 4.493 0 0 1 8 12.5a4.49 4.49 0 0 1 1.606-3.446l-.367-.225L8 9.586l-1.239-.757ZM16 4.697v4.974A4.491 4.491 0 0 0 12.5 8a4.49 4.49 0 0 0-1.965.45l-.338-.207L16 4.697Z" />
78+
<path
79+
d="M16 12.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Zm-1.993-1.679a.5.5 0 0 0-.686.172l-1.17 1.95-.547-.547a.5.5 0 0 0-.708.708l.774.773a.75.75 0 0 0 1.174-.144l1.335-2.226a.5.5 0 0 0-.172-.686Z" />
80+
</svg>
81+
<div class="name text-muted text-decoration-none text-center pt-1">Contact Us</div>
82+
</a>
83+
</a>
84+
<a href="{% url 'quiz:about' %}">
85+
86+
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="#ff8042" class="bi bi-book-half"
87+
viewBox="0 0 16 16">
88+
<path
89+
d="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" />
90+
</svg>
91+
<div class="name text-muted text-decoration-none text-center pt-1">About Us</div>
92+
</a>
93+
</span>
94+
95+
</div>
96+
</nav>
97+
{% endif %}

quiz/templates/quiz/aboutus.html

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{% extends 'base.html' %}
2+
{% block title %}
3+
About Us
4+
{% endblock title %}
5+
{% block content %}
6+
<div class="container">
7+
<div class="display-2">About Us</div>
8+
<div class="fs-4">
9+
10+
We are a team of passionate individuals who believe that learning should be fun and accessible to everyone. That's why
11+
we created this Quiz Application - to bring the excitement of quizzes to your fingertips.
12+
13+
With our app, you can test your knowledge on a wide range of topics, from history and science to pop culture and
14+
entertainment. Our quizzes are designed to be engaging, challenging, and thought-provoking, making sure that you learn
15+
something new every time you play.
16+
17+
We are constantly updating our database with new quizzes and questions, ensuring that there is always something new for
18+
you to discover. Our user-friendly interface makes it easy for you to navigate and find the quizzes that interest you
19+
the most.
20+
21+
Our mission is to provide a platform for anyone to learn, explore and challenge themselves in a fun and interactive way.
22+
Whether you're a student looking to brush up on your knowledge, or simply someone looking for a fun way to pass the
23+
time, our Quiz Application has something for everyone.
24+
25+
So, why not challenge yourself and see how much you know? Download our Quiz Application today and start exploring the
26+
world of quizzes!
27+
28+
Thank you for choosing our Quiz Application. We can't wait for you to join the millions of users who have already
29+
discovered the joy of learning with us.
30+
</div>
31+
</div>
32+
{% endblock content %}

0 commit comments

Comments
 (0)