migarate exam_user_status

This commit is contained in:
Ross
2024-07-22 17:25:12 +01:00
parent ca4c8d31b9
commit aeaf0fcb2e
7 changed files with 93 additions and 46 deletions
+15 -7
View File
@@ -3,7 +3,7 @@ from typing import List
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from ninja import ModelSchema, Router from ninja import ModelSchema, Router
from generic.models import CidUser, ExamUserStatus from generic.models import CidUser, CidUserExam, ExamUserStatus
from .models import AnatomyQuestion as Question, Exam from .models import AnatomyQuestion as Question, Exam
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
@@ -29,6 +29,13 @@ class UserUserSchema(ModelSchema):
model = get_user_model() model = get_user_model()
model_fields = ["id", "email"] model_fields = ["id", "email"]
class CidUserExamSchema(ModelSchema):
cid_user : CidUserSchema | None
user_user : UserUserSchema | None
class Config:
model = CidUserExam
model_fields = ["id"]
class ExamStatusSchema(ModelSchema): class ExamStatusSchema(ModelSchema):
class Config: class Config:
model = ExamUserStatus model = ExamUserStatus
@@ -36,8 +43,9 @@ class ExamStatusSchema(ModelSchema):
class ExamUserStatusSchema(ModelSchema): class ExamUserStatusSchema(ModelSchema):
cid_user : CidUserSchema | None #cid_user : CidUserSchema | None
user_user : UserUserSchema | None #user_user : UserUserSchema | None
cid_user_exam : CidUserExamSchema | None
class Config: class Config:
model = ExamUserStatus model = ExamUserStatus
model_fields = ["id", "datetime", "status", "extra"] model_fields = ["id", "datetime", "status", "extra"]
@@ -90,8 +98,8 @@ def get_exam_user_status_all(request, exam_id: int, latest:bool=True):
results = exam.exam_user_status.all() results = exam.exam_user_status.all()
if latest: if latest:
cid_users = exam.exam_user_status.filter(cid_user__isnull=False).order_by("cid_user", "-datetime").distinct("cid_user") cid_users = exam.exam_user_status.filter(cid_user_exam__cid_user__isnull=False).order_by("cid_user_exam", "-datetime")#.distinct("cid_user")
user_users = exam.exam_user_status.filter(user_user__isnull=False).order_by("user_user", "-datetime").distinct("user_user") user_users = exam.exam_user_status.filter(cid_user_exam__user_user__isnull=False).order_by("cid_user_exam", "-datetime")#.distinct("user_user")
results = list(cid_users) results = list(cid_users)
results.extend(list(user_users)) results.extend(list(user_users))
@@ -107,7 +115,7 @@ def get_exam_user_status_cid_user(request, exam_id: int, cid: int):
print(exam_id, cid) print(exam_id, cid)
return exam.exam_user_status.filter(cid_user__cid=cid) return exam.exam_user_status.filter(cid_user_exam__cid_user__cid=cid)
@router.get('/exam/{exam_id}/user_status/{user_id}/user', response=List[ExamStatusSchema]) @router.get('/exam/{exam_id}/user_status/{user_id}/user', response=List[ExamStatusSchema])
def get_exam_user_status_user_user(request, exam_id: int, user_id: int): def get_exam_user_status_user_user(request, exam_id: int, user_id: int):
@@ -115,4 +123,4 @@ def get_exam_user_status_user_user(request, exam_id: int, user_id: int):
if not exam.check_user_can_edit(request.user): if not exam.check_user_can_edit(request.user):
raise HttpError(HTTPStatus.UNAUTHORIZED,"Exam author required") raise HttpError(HTTPStatus.UNAUTHORIZED,"Exam author required")
return exam.exam_user_status.filter(user_user=user_id) return exam.exam_user_status.filter(cid_user_exam__user_user=user_id)
-1
View File
@@ -811,7 +811,6 @@ class CaseCollection(ExamOrCollectionGenericBase):
) )
exam_user_status = GenericRelation(ExamUserStatus) exam_user_status = GenericRelation(ExamUserStatus)
cid_user_exam = GenericRelation(CidUserExam)
feedback_once_collection_complete = models.BooleanField(default=True, help_text="If true feedback is only given once the collection is complete. If false feedback is given after each case.") feedback_once_collection_complete = models.BooleanField(default=True, help_text="If true feedback is only given once the collection is complete. If false feedback is given after each case.")
+4 -10
View File
@@ -1988,15 +1988,9 @@ def collection_take_overview(
cid_user_exam.completed = True cid_user_exam.completed = True
cid_user_exam.save() cid_user_exam.save()
if cid is not None: collection.exam_user_status.create(
c = CidUser.objects.get(cid=cid) cid_user_exam=cid_user_exam, status="submitted", extra="manual submission"
collection.exam_user_status.create( )
cid_user=c, user_user=None, status="submitted", extra="manual submission"
)
else:
collection.exam_user_status.create(
cid_user=None, user_user=request.user, status="submitted", extra="manual submission"
)
return HttpResponse("True") return HttpResponse("True")
else: else:
@@ -2841,7 +2835,7 @@ def collection_reset_answers(request, exam_id: int):
collection.exam_user_status.all().delete() collection.exam_user_status.all().delete()
# CidUserExams # CidUserExams
CidUserExam.objects.filter(exam=collection).delete() collection.cid_users.delete()
else: else:
@@ -0,0 +1,19 @@
# Generated by Django 5.0.2 on 2024-07-22 10:50
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('generic', '0013_examcollection_archive'),
]
operations = [
migrations.AddField(
model_name='examuserstatus',
name='cid_user_exam',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='generic.ciduserexam'),
),
]
@@ -0,0 +1,34 @@
# Generated by Django 5.0.2 on 2024-07-22 10:53
from django.db import migrations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from generic.models import ExamUserStatus, CidUserExam
def change_exam_user_status(apps, schema_editor):
ExamUserStatus: "ExamUserStatus" = apps.get_model("generic", "ExamUserStatus")
CidUserExam: "CidUserExam" = apps.get_model("generic", "CidUserExam")
for exam_user_status in ExamUserStatus.objects.all():
cid_user_exam, created = CidUserExam.objects.get_or_create(content_type=exam_user_status.content_type, object_id=exam_user_status.object_id, user_user=exam_user_status.user_user, cid_user=exam_user_status.cid_user)
exam_user_status.cid_user_exam = cid_user_exam
exam_user_status.save()
def change_exam_user_status_reverse(apps, schema_editor):
ExamUserStatus: "ExamUserStatus" = apps.get_model("generic", "ExamUserStatus")
for exam_user_status in ExamUserStatus.objects.all():
exam_user_status.cid_user_exam = None
exam_user_status.save()
class Migration(migrations.Migration):
dependencies = [
('generic', '0014_examuserstatus_cid_user_exam'),
]
operations = [
migrations.RunPython(change_exam_user_status, change_exam_user_status_reverse)
]
+8 -6
View File
@@ -1074,14 +1074,16 @@ class ExamUserStatus(models.Model):
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
exam = GenericForeignKey("content_type", "object_id") exam = GenericForeignKey("content_type", "object_id")
cid_user_exam = models.ForeignKey("CidUserExam", blank=True, null=True, on_delete=models.SET_NULL)
def __str__(self): def __str__(self):
self.cid_user: "CidUser" self.cid_user_exam: "CidUserExam"
if self.cid_user: if self.cid_user_exam.cid_user:
user = self.cid_user.cid user = self.cid_user_exam.cid_user.cid
email = self.cid_user.email email = self.cid_user_exam.cid_user.email
return f"{self.datetime:%Y-%m-%d %H:%M:%S}: [CID] {user} ({email}) - {self.status} ({self.extra})" return f"{self.datetime:%Y-%m-%d %H:%M:%S}: [CID] {user} ({email}) - {self.status} ({self.extra})"
else: else:
user = self.user_user.username user = self.cid_user_exam.user_user.username
return f"{self.datetime:%Y-%m-%d %H:%M:%S}: [USER] {user} - {self.status} ({self.extra})" return f"{self.datetime:%Y-%m-%d %H:%M:%S}: [USER] {user} - {self.status} ({self.extra})"
@@ -1440,7 +1442,7 @@ class CidUserExam(models.Model):
else: else:
end_time = f"{ self.end_time:%Y-%m-%d %H:%M }" end_time = f"{ self.end_time:%Y-%m-%d %H:%M }"
return f"{user}: {start_time} {end_time}" return f"{self.exam} / {user}: {start_time} {end_time}"
CID_GROUP_EXAMS = ( CID_GROUP_EXAMS = (
+13 -22
View File
@@ -1105,9 +1105,9 @@ class ExamViews(View, LoginRequiredMixin):
raise PermissionDenied raise PermissionDenied
if cid is not None: if cid is not None:
statuses = exam.exam_user_status.filter(cid_user__cid=cid) statuses = exam.exam_user_status.filter(cid_user_exam__cid_user__cid=cid)
elif user_id is not None: elif user_id is not None:
statuses = exam.exam_user_status.filter(user_user__id=user_id) statuses = exam.exam_user_status.filter(cid_user_exam__user_user__id=user_id)
else: else:
statuses = exam.exam_user_status.all() statuses = exam.exam_user_status.all()
@@ -1692,17 +1692,14 @@ class ExamViews(View, LoginRequiredMixin):
cid_user_exam = exam.get_or_create_cid_user_exam( cid_user_exam = exam.get_or_create_cid_user_exam(
user_user=request.user, start_time=t user_user=request.user, start_time=t
) )
exam.exam_user_status.create(
cid_user=None, user_user=request.user, status="submitted", extra="manual submission"
)
else: else:
c = CidUser.objects.filter(cid=request.POST.get("cid")).first() c = CidUser.objects.filter(cid=request.POST.get("cid")).first()
cid_user_exam = exam.get_or_create_cid_user_exam( cid_user_exam = exam.get_or_create_cid_user_exam(
cid_user=c, start_time=t cid_user=c, start_time=t
) )
exam.exam_user_status.create( exam.exam_user_status.create(
cid_user=c, user_user=None, status="submitted", extra="manual submission" cid_user_exam=cid_user_exam, status="submitted", extra="manual submission"
) )
cid_user_exam.end_time = timezone.now() cid_user_exam.end_time = timezone.now()
cid_user_exam.save() cid_user_exam.save()
@@ -1738,14 +1735,11 @@ class ExamViews(View, LoginRequiredMixin):
# Log exam access # Log exam access
if exam.exam_mode: if exam.exam_mode:
if cid is not None: cid_user_exam = exam.get_or_create_cid_user_exam(
user = None cid=cid, user_user=request.user
cid_user = CidUser.objects.get(cid=cid) )
else:
user = request.user
cid_user = None
exam.exam_user_status.create( exam.exam_user_status.create(
cid_user=cid_user, user_user=user, status="downloaded" cid_user_exam=cid_user_exam, status="downloaded"
) )
path = "{0}{1}/exam/{2}.json".format(settings.MEDIA_ROOT, self.app_name, pk) path = "{0}{1}/exam/{2}.json".format(settings.MEDIA_ROOT, self.app_name, pk)
@@ -1818,14 +1812,11 @@ class ExamViews(View, LoginRequiredMixin):
# Log exam access # Log exam access
if exam.exam_mode: if exam.exam_mode:
user = request.user cid_user_exam = exam.get_or_create_cid_user_exam(
if cid is not None: cid=cid, user_user=request.user
user = None )
cid_user = CidUser.objects.get(cid=cid)
else:
cid_user = None
exam.exam_user_status.create( exam.exam_user_status.create(
cid_user=cid_user, user_user=user, status="downloaded", extra="unbased" cid_user_exam=cid_user_exam, status="downloaded", extra="unbased"
) )
return JsonResponse(exam_json) return JsonResponse(exam_json)