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,
@@ -28,7 +30,10 @@ class CidUserAnswerForm(ModelForm):
self.fields['answer'].required = False
# This should be made generic?
class ExamForm(ModelForm):
class Meta:
class ExamForm(ExamFormMixin, ModelForm):
class Meta(ExamFormMixin.Meta):
model = Exam
fields = ["name", "time_limit", "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),
('sbas', '0013_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_sbas_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='sba_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='sba_user_user_groups', to='generic.UserUserGroup'),
),
]
+24 -1
View File
@@ -11,7 +11,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
@@ -170,6 +170,21 @@ class Exam(ExamBase):
settings.AUTH_USER_MODEL, blank=True, related_name="user_sba_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="sba_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="sba_user_user_groups"
)
def get_take_url(self):
return reverse("sbas:exam_start", kwargs={"pk": self.pk})
@@ -189,6 +204,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_sbas_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
@@ -2,7 +2,7 @@ from reversion.views import RevisionMixin
from generic.mixins import SuperuserRequiredMixin
from django.views.generic.detail import DetailView
from generic.models import CidUser
from sbas.forms import CidUserAnswerForm, ExamForm
from sbas.forms import CidUserAnswerForm, ExamAuthorForm, ExamForm
from django.shortcuts import render, get_object_or_404, redirect
from django.views.decorators.csrf import csrf_exempt
from django import forms
@@ -40,7 +40,7 @@ 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
@@ -378,6 +378,10 @@ class ExamUpdate(
#
# return Exam.objects.filter(author__id=user.id)
class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView):
model = Exam
form_class = ExamAuthorForm
class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
model = Exam