This commit is contained in:
Ross
2022-05-21 22:09:37 +01:00
parent 851e681400
commit 781b6bc1fe
26 changed files with 311 additions and 70 deletions
+8 -3
View File
@@ -8,6 +8,8 @@ from django.forms import (
)
from django.forms import inlineformset_factory
from generic.forms import ExamAuthorFormMixin, ExamFormMixin
from .models import (
Question,
CidUserAnswer,
@@ -30,7 +32,10 @@ class CidUserAnswerForm(ModelForm):
# This should be made generic?
class ExamForm(ModelForm):
class Meta:
class ExamForm(ExamFormMixin, ModelForm):
class Meta(ExamFormMixin.Meta):
model = Exam
fields = ["name", "time_limit", "open_access", "exam_mode", "active", "archive"]
class ExamAuthorForm(ExamAuthorFormMixin):
class Meta(ExamAuthorFormMixin.Meta):
model = Exam
@@ -0,0 +1,32 @@
# Generated by Django 3.2.13 on 2022-05-21 20:35
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('generic', '0032_userprofile_registration_number'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('physics', '0021_exam_valid_user_users'),
]
operations = [
migrations.AddField(
model_name='ciduseranswer',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_physics_user_answers', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='exam',
name='cid_user_groups',
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='physics_cid_user_groups', to='generic.CidUserGroup'),
),
migrations.AddField(
model_name='exam',
name='user_user_groups',
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='physics_user_user_groups', to='generic.UserUserGroup'),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 3.2.13 on 2022-05-21 20:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('generic', '0032_userprofile_registration_number'),
('physics', '0022_auto_20220521_2135'),
]
operations = [
migrations.AlterField(
model_name='exam',
name='cid_user_groups',
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='physics_exam_cid_user_groups', to='generic.CidUserGroup'),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 3.2.13 on 2022-05-21 20:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('generic', '0032_userprofile_registration_number'),
('physics', '0023_alter_exam_cid_user_groups'),
]
operations = [
migrations.AlterField(
model_name='exam',
name='cid_user_groups',
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='physics_cid_user_groups', to='generic.CidUserGroup'),
),
]
+25 -2
View File
@@ -12,7 +12,7 @@ from django.utils.translation import gettext_lazy as _
from sortedm2m.fields import SortedManyToManyField
from generic.models import CidUser, ExamBase, QuestionNote
from generic.models import CidUser, CidUserGroup, ExamBase, QuestionNote, UserUserGroup
import reversion
@@ -131,7 +131,7 @@ class Question(models.Model):
return [self.a, self.b, self.c, self.d, self.e]
@reversion.register
#@reversion.register
class Exam(ExamBase):
app_name = "physics"
@@ -160,6 +160,21 @@ class Exam(ExamBase):
settings.AUTH_USER_MODEL, blank=True, related_name="user_physics_exams"
)
cid_user_groups = models.ManyToManyField(
CidUserGroup,
blank=True,
help_text="These groups define which candidates are able to be added to the exams/collection.",
related_name="physics_cid_user_groups"
)
user_user_groups = models.ManyToManyField(
UserUserGroup,
blank=True,
help_text="These groups define which candidates are able to be added to the exams/collection.",
related_name="physics_user_user_groups"
)
def get_take_url(self):
return reverse("physics:exam_start", kwargs={"pk": self.pk})
@@ -179,6 +194,14 @@ class CidUserAnswer(models.Model):
cid = models.IntegerField(blank=True, null=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True,
null=True,
related_name="user_physics_user_answers",
)
# Each user answer is associated with a particular exam
exam = models.ForeignKey(
Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True
+1
View File
@@ -26,6 +26,7 @@ urlpatterns = [
name="exam_take_overview",
),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path("exam/<int:pk>/authors", views.ExamAuthorUpdate.as_view(), name="exam_authors"),
path(
"exam/<int:pk>/scores",
views.GenericExamViews.exam_scores_cid,
+6 -2
View File
@@ -42,14 +42,14 @@ import json
import statistics
import plotly.express as px
from generic.views import ExamCloneMixin, ExamViews, GenericViewBase
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamViews, GenericViewBase
from rest_framework import viewsets, permissions
from rest_framework.pagination import PageNumberPagination
from django.core.exceptions import PermissionDenied
from .forms import CidUserAnswerForm, ExamForm
from .forms import CidUserAnswerForm, ExamAuthorForm, ExamForm
from .decorators import (
user_is_author_or_physics_checker,
user_is_exam_author_or_physics_checker,
@@ -391,6 +391,10 @@ class ExamClone(AuthorOrCheckerRequiredMixin, ExamCloneMixin, ExamCreate):
"""Clone exam view"""
class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView):
model = Exam
form_class = ExamAuthorForm
class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
model = Exam
template_name = "exam_confirm_delete.html"