Pamela Fox
commited on
Commit
·
1dbd98a
1
Parent(s):
013c0dc
Admin changes
Browse files- quizzes/admin.py +12 -4
- quizzes/migrations/0002_remove_question_answer_status_and_more.py +32 -0
- quizzes/models.py +15 -11
- quizzes/templates/quizzes/display.html +32 -0
- quizzes/templates/quizzes/index.html +19 -0
- quizzes/urls.py +3 -1
- quizzes/views.py +14 -3
quizzes/admin.py
CHANGED
@@ -1,7 +1,15 @@
|
|
1 |
from django.contrib import admin
|
2 |
-
from .models import Quiz, Question, FreeTextAnswer, MultipleChoiceAnswer
|
3 |
|
4 |
admin.site.register(Quiz)
|
5 |
-
|
6 |
-
admin.
|
7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from django.contrib import admin
|
2 |
+
from .models import Quiz, Question, Answer, FreeTextAnswer, MultipleChoiceAnswer
|
3 |
|
4 |
admin.site.register(Quiz)
|
5 |
+
|
6 |
+
class FreeTextAnswerInline(admin.StackedInline):
|
7 |
+
model = FreeTextAnswer
|
8 |
+
|
9 |
+
class MultipleChoiceAnswerInline(admin.StackedInline):
|
10 |
+
model = MultipleChoiceAnswer
|
11 |
+
|
12 |
+
class QuestionAdmin(admin.ModelAdmin):
|
13 |
+
inlines = [FreeTextAnswerInline, MultipleChoiceAnswerInline]
|
14 |
+
|
15 |
+
admin.site.register(Question, QuestionAdmin)
|
quizzes/migrations/0002_remove_question_answer_status_and_more.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 4.1.1 on 2022-09-15 00:57
|
2 |
+
|
3 |
+
from django.db import migrations, models
|
4 |
+
import django.db.models.deletion
|
5 |
+
|
6 |
+
|
7 |
+
class Migration(migrations.Migration):
|
8 |
+
|
9 |
+
dependencies = [
|
10 |
+
("quizzes", "0001_initial"),
|
11 |
+
]
|
12 |
+
|
13 |
+
operations = [
|
14 |
+
migrations.RemoveField(
|
15 |
+
model_name="question",
|
16 |
+
name="answer_status",
|
17 |
+
),
|
18 |
+
migrations.AlterField(
|
19 |
+
model_name="freetextanswer",
|
20 |
+
name="question",
|
21 |
+
field=models.OneToOneField(
|
22 |
+
on_delete=django.db.models.deletion.CASCADE, to="quizzes.question"
|
23 |
+
),
|
24 |
+
),
|
25 |
+
migrations.AlterField(
|
26 |
+
model_name="multiplechoiceanswer",
|
27 |
+
name="question",
|
28 |
+
field=models.OneToOneField(
|
29 |
+
on_delete=django.db.models.deletion.CASCADE, to="quizzes.question"
|
30 |
+
),
|
31 |
+
),
|
32 |
+
]
|
quizzes/models.py
CHANGED
@@ -28,10 +28,9 @@ class Quiz(models.Model):
|
|
28 |
class Question(models.Model):
|
29 |
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
|
30 |
prompt = models.CharField(max_length=200)
|
31 |
-
answer_status = models.CharField(default='unanswered', max_length=16)
|
32 |
|
33 |
def __str__(self):
|
34 |
-
return
|
35 |
|
36 |
def display(self):
|
37 |
print(self.prompt)
|
@@ -44,15 +43,22 @@ class Question(models.Model):
|
|
44 |
print(f"Sorry, it was: {self.answer.correct_answer}")
|
45 |
self.answer_status = 'incorrect'
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
|
|
51 |
correct_answer = models.CharField(max_length=200)
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
case_sensitive = models.BooleanField(default=False)
|
53 |
|
54 |
def __str__(self):
|
55 |
-
return
|
56 |
|
57 |
def is_correct(self, user_answer):
|
58 |
if not self.case_sensitive:
|
@@ -65,13 +71,11 @@ class FreeTextAnswer(models.Model):
|
|
65 |
else:
|
66 |
print("Type your answer in (don't worry about capitalization):")
|
67 |
|
68 |
-
class MultipleChoiceAnswer(
|
69 |
-
question = models.ForeignKey(Question, on_delete=models.CASCADE)
|
70 |
-
correct_answer = models.CharField(max_length=200)
|
71 |
choices = fields.ArrayField(models.CharField(max_length=200, blank=True))
|
72 |
|
73 |
def __str__(self):
|
74 |
-
return f"
|
75 |
|
76 |
def is_correct(self, user_answer):
|
77 |
"""Assumes user answer is number corresponding to answer."""
|
|
|
28 |
class Question(models.Model):
|
29 |
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
|
30 |
prompt = models.CharField(max_length=200)
|
|
|
31 |
|
32 |
def __str__(self):
|
33 |
+
return self.prompt
|
34 |
|
35 |
def display(self):
|
36 |
print(self.prompt)
|
|
|
43 |
print(f"Sorry, it was: {self.answer.correct_answer}")
|
44 |
self.answer_status = 'incorrect'
|
45 |
|
46 |
+
class Answer(models.Model):
|
47 |
+
question = models.OneToOneField(
|
48 |
+
Question,
|
49 |
+
on_delete=models.CASCADE
|
50 |
+
)
|
51 |
correct_answer = models.CharField(max_length=200)
|
52 |
+
|
53 |
+
|
54 |
+
class Meta:
|
55 |
+
abstract = True
|
56 |
+
|
57 |
+
class FreeTextAnswer(Answer):
|
58 |
case_sensitive = models.BooleanField(default=False)
|
59 |
|
60 |
def __str__(self):
|
61 |
+
return self.correct_answer
|
62 |
|
63 |
def is_correct(self, user_answer):
|
64 |
if not self.case_sensitive:
|
|
|
71 |
else:
|
72 |
print("Type your answer in (don't worry about capitalization):")
|
73 |
|
74 |
+
class MultipleChoiceAnswer(Answer):
|
|
|
|
|
75 |
choices = fields.ArrayField(models.CharField(max_length=200, blank=True))
|
76 |
|
77 |
def __str__(self):
|
78 |
+
return f"{self.correct_answer} from {self.choices}"
|
79 |
|
80 |
def is_correct(self, user_answer):
|
81 |
"""Assumes user answer is number corresponding to answer."""
|
quizzes/templates/quizzes/display.html
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE HTML>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<meta charset="utf-8">
|
5 |
+
<meta name="viewport" content="width=device-width">
|
6 |
+
<title>Quiz {{ quiz.id }}</title>
|
7 |
+
</head>
|
8 |
+
<body>
|
9 |
+
<h1>{{ quiz.name }}</h1>
|
10 |
+
|
11 |
+
<form action="{% url 'quizzes:grade' question.id %}" method="post">
|
12 |
+
{% csrf_token %}
|
13 |
+
{% for question in quiz.question_set.all %}
|
14 |
+
<section>
|
15 |
+
<h3>{{ question.prompt }}</h3>
|
16 |
+
{% if question.freetextanswer %}
|
17 |
+
<input type="text" name="{{ question.pk }}">
|
18 |
+
{% else %}
|
19 |
+
{% for choice in question.multiplechoiceanswer.choices %}
|
20 |
+
<label>
|
21 |
+
<input type="radio" name="{{ question.pk }}" value="{{ choice }}">
|
22 |
+
{{ choice}}
|
23 |
+
</label>
|
24 |
+
{% endfor %}
|
25 |
+
{% endif %}
|
26 |
+
</section>
|
27 |
+
{% endfor %}
|
28 |
+
|
29 |
+
<button type="submit">Check answers</button>
|
30 |
+
</form>
|
31 |
+
</body>
|
32 |
+
</html>
|
quizzes/templates/quizzes/index.html
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE HTML>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<meta charset="utf-8">
|
5 |
+
<meta name="viewport" content="width=device-width">
|
6 |
+
<title>Quizzes</title>
|
7 |
+
</head>
|
8 |
+
<body>
|
9 |
+
{% if quiz_list %}
|
10 |
+
<ul>
|
11 |
+
{% for quiz in quiz_list %}
|
12 |
+
<li><a href="{% url 'quizzes:display' quiz.id %}">{{ quiz.name }}</a></li>
|
13 |
+
{% endfor %}
|
14 |
+
</ul>
|
15 |
+
{% else %}
|
16 |
+
<p>No quizzes are available.</p>
|
17 |
+
{% endif %}
|
18 |
+
</body>
|
19 |
+
</html>
|
quizzes/urls.py
CHANGED
@@ -2,9 +2,11 @@ from django.urls import path
|
|
2 |
|
3 |
from . import views
|
4 |
|
|
|
|
|
5 |
urlpatterns = [
|
6 |
path('', views.index, name='index'),
|
7 |
-
# ex: /polls/5/
|
8 |
path('<int:quiz_id>/', views.display, name='display'),
|
|
|
9 |
|
10 |
]
|
|
|
2 |
|
3 |
from . import views
|
4 |
|
5 |
+
app_name = 'quizzes'
|
6 |
+
|
7 |
urlpatterns = [
|
8 |
path('', views.index, name='index'),
|
|
|
9 |
path('<int:quiz_id>/', views.display, name='display'),
|
10 |
+
path('<int:quiz_id>/grade/', views.grade, name='grade'),
|
11 |
|
12 |
]
|
quizzes/views.py
CHANGED
@@ -1,7 +1,18 @@
|
|
1 |
-
from django.
|
|
|
|
|
2 |
|
3 |
def index(request):
|
4 |
-
|
|
|
|
|
|
|
5 |
|
6 |
def display(request, quiz_id):
|
7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.shortcuts import get_object_or_404,render
|
2 |
+
|
3 |
+
from .models import Quiz
|
4 |
|
5 |
def index(request):
|
6 |
+
quiz_list = Quiz.objects.all()
|
7 |
+
context = {'quiz_list': quiz_list}
|
8 |
+
return render(request, 'quizzes/index.html', context)
|
9 |
+
|
10 |
|
11 |
def display(request, quiz_id):
|
12 |
+
quiz = get_object_or_404(Quiz, pk=quiz_id)
|
13 |
+
return render(request, 'quizzes/display.html', {'quiz': quiz})
|
14 |
+
|
15 |
+
|
16 |
+
def grade(request, quiz_id):
|
17 |
+
quiz = get_object_or_404(Quiz, pk=quiz_id)
|
18 |
+
return render(request, 'quizzes/display.html', {'quiz': quiz})
|