rename CidUserAnswer to UserAnswer

This commit is contained in:
Ross
2023-05-15 11:15:17 +01:00
parent 7aa78c2807
commit d05752b2dc
49 changed files with 346 additions and 251 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ from .models import (
#Examination,
QuestionType,
Answer,
CidUserAnswer,
UserAnswer,
Exam,
Modality,
Region,
@@ -54,7 +54,7 @@ class ExamAdmin(VersionAdmin, admin.ModelAdmin):
admin.site.register(AnatomyQuestion, AnatomyAdmin)
#admin.site.register(Examination)
admin.site.register(QuestionType)
admin.site.register(CidUserAnswer)
admin.site.register(UserAnswer)
admin.site.register(Exam, ExamAdmin)
admin.site.register(Modality)
admin.site.register(Region)
+5 -5
View File
@@ -1,8 +1,8 @@
import django_filters
from .models import AnatomyQuestion, CidUserAnswer, Exam
from .models import AnatomyQuestion, UserAnswer, Exam
#from generic.filters import CidUserAnswerFilter
#from generic.filters import UserAnswerFilter
from django.contrib.auth.models import User
@@ -46,9 +46,9 @@ class AnatomyQuestionFilter(django_filters.FilterSet):
super(AnatomyQuestionFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
class AnatomyCidUserAnswerFilter(django_filters.FilterSet):
class AnatomyUserAnswerFilter(django_filters.FilterSet):
class Meta:
model= CidUserAnswer
model= UserAnswer
fields = (
"cid",
"user",
@@ -63,5 +63,5 @@ class AnatomyCidUserAnswerFilter(django_filters.FilterSet):
def __init__(self, data=None, queryset=None, prefix=None, strict=None, user=None, request=None):
if not request.user.groups.filter(name="anatomy_checker").exists():
queryset = queryset.filter(open_access=True) | queryset.filter(author__id=request.user.id)
super(AnatomyCidUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
super(AnatomyUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
+2 -2
View File
@@ -12,7 +12,7 @@ from generic.forms import ExamAuthorFormMixin, ExamFormMixin
from .models import (
Answer,
CidUserAnswer,
UserAnswer,
AnatomyQuestion,
# Examination,
BodyPart,
@@ -32,7 +32,7 @@ from dal import autocomplete
class AnatomyAnswerForm(ModelForm):
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = ("answer",)
@@ -0,0 +1,19 @@
# Generated by Django 4.1.4 on 2023-05-15 10:14
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('anatomy', '0068_alter_ciduseranswer_options'),
]
operations = [
migrations.RenameModel(
old_name='CidUserAnswer',
new_name='UserAnswer',
),
]
+3 -3
View File
@@ -16,7 +16,7 @@ from sortedm2m.fields import SortedManyToManyField
import string
from generic.models import CidUser, CidUserGroup, ExamUserStatus, Examination, ExamBase, QuestionNote, CidUserAnswerBase, UserUserGroup
from generic.models import CidUser, CidUserGroup, ExamUserStatus, Examination, ExamBase, QuestionNote, UserAnswerBase, UserUserGroup
from collections import defaultdict
from helpers.images import image_as_base64
@@ -467,7 +467,7 @@ class Exam(ExamBase):
@reversion.register
class CidUserAnswer(CidUserAnswerBase):
class UserAnswer(UserAnswerBase):
"""User answers by candidate"""
question = models.ForeignKey(
@@ -504,7 +504,7 @@ class CidUserAnswer(CidUserAnswerBase):
def save(self, *args, **kwargs):
self.clean()
return super(CidUserAnswer, self).save(*args, **kwargs)
return super(UserAnswer, self).save(*args, **kwargs)
def clean(self):
if self.answer:
+4 -4
View File
@@ -1,7 +1,7 @@
import django_tables2 as tables
from django_tables2.utils import A
from .models import AnatomyQuestion, CidUserAnswer
from .models import AnatomyQuestion, UserAnswer
from django.utils.html import format_html
@@ -9,7 +9,7 @@ from easy_thumbnails.files import get_thumbnailer
from easy_thumbnails.exceptions import InvalidImageFormatError
#from generic.tables import CidUserAnswerTable
#from generic.tables import UserAnswerTable
class ImageColumn(tables.Column):
@@ -64,7 +64,7 @@ class AnatomyQuestionTable(tables.Table):
*args,
**kwargs,
)
class AnatomyCidUserAnswerTable(tables.Table):
class AnatomyUserAnswerTable(tables.Table):
select = tables.CheckBoxColumn(accessor=("pk"))
delete = tables.LinkColumn(
"anatomy:user_answer_delete", text="Delete", args=[A("pk")], orderable=False
@@ -74,7 +74,7 @@ class AnatomyCidUserAnswerTable(tables.Table):
args=[A('pk')],
orderable=False)
class Meta:
model = CidUserAnswer
model = UserAnswer
template_name = "django_tables2/bootstrap4.html"
fields = (
"cid",
+3 -3
View File
@@ -73,15 +73,15 @@ urlpatterns = [
),
path(
"user_answers/",
views.CidUserAnswerTableView.as_view(),
views.UserAnswerTableView.as_view(),
name="user_answer_table_view",
),
path(
"user_answers/<int:pk>", views.CidUserAnswerView.as_view(), name="user_answer_view"
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view"
),
path(
"user_answers/<int:pk>/delete",
views.CidUserAnswerDelete.as_view(),
views.UserAnswerDelete.as_view(),
name="user_answer_delete",
),
path(
+19 -19
View File
@@ -41,7 +41,7 @@ from .forms import (
from .models import (
AnatomyQuestion,
BodyPart,
CidUserAnswer,
UserAnswer,
# Examination,
Structure,
Exam,
@@ -55,8 +55,8 @@ from reversion.views import RevisionMixin
from .decorators import user_is_author_or_anatomy_checker
from .tables import AnatomyQuestionTable, AnatomyCidUserAnswerTable
from .filters import AnatomyQuestionFilter, AnatomyCidUserAnswerFilter
from .tables import AnatomyQuestionTable, AnatomyUserAnswerTable
from .filters import AnatomyQuestionFilter, AnatomyUserAnswerFilter
from django_tables2 import SingleTableView, SingleTableMixin
from django_filters.views import FilterView
@@ -161,12 +161,12 @@ def answer_question(request, pk):
# }
#
# # Get data for flagged
# # answered_questions = CidUserAnswer.objects.filter(user=request.user).values_list("question__pk", flat=True)
# user_answer_data = CidUserAnswer.objects.filter(user=request.user).values_list(
# # answered_questions = UserAnswer.objects.filter(user=request.user).values_list("question__pk", flat=True)
# user_answer_data = UserAnswer.objects.filter(user=request.user).values_list(
# "question__pk", "answer", "flagged"
# )
# # flagged_questions = CidUserAnswer.objects.filter(user=request.user, flagged=True).values_list("question__pk", flat=True)
# # flagged_questions I= CidUserAnswer.filter(user=request.user, ).values_list("question__pk", flat=True)
# # flagged_questions = UserAnswer.objects.filter(user=request.user, flagged=True).values_list("question__pk", flat=True)
# # flagged_questions I= UserAnswer.filter(user=request.user, ).values_list("question__pk", flat=True)
#
# answered_questions = set()
# flagged_questions = set()
@@ -215,7 +215,7 @@ def answer_question(request, pk):
# def flag_question(request):
# pk = request.GET.get("pk", None)
# ans = CidUserAnswer.objects.filter(user=request.user, question__pk=pk).first()
# ans = UserAnswer.objects.filter(user=request.user, question__pk=pk).first()
# ans.flagged = not ans.flagged
# ans.save()
# data = {"flagged": ans.flagged}
@@ -384,7 +384,7 @@ def exam_scores_refresh(request, pk):
questions = exam.exam_questions.all()
cids = CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
cids = UserAnswer.objects.filter(question__in=questions, exam__id=pk)
# Force a score update
for c in cids:
@@ -733,24 +733,24 @@ def question_save_annotation(request, pk):
GenericExamViews = ExamViews(
Exam, AnatomyQuestion, Answer, CidUserAnswer, "anatomy", "anatomy"
Exam, AnatomyQuestion, Answer, UserAnswer, "anatomy", "anatomy"
)
class CidUserAnswerView(SuperuserRequiredMixin, DetailView):
model = CidUserAnswer
class UserAnswerView(SuperuserRequiredMixin, DetailView):
model = UserAnswer
class CidUserAnswerTableView(SuperuserRequiredMixin, SingleTableMixin, FilterView):
model = CidUserAnswer
table_class = AnatomyCidUserAnswerTable
class UserAnswerTableView(SuperuserRequiredMixin, SingleTableMixin, FilterView):
model = UserAnswer
table_class = AnatomyUserAnswerTable
template_name = "anatomy/user_answer_question_view.html"
filterset_class = AnatomyCidUserAnswerFilter
filterset_class = AnatomyUserAnswerFilter
class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = UserAnswer
template_name = "user_answer_delete.html"
success_url = reverse_lazy("anatomy:user_answer_table_view")
@@ -797,7 +797,7 @@ class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, U
GenericViews = GenericViewBase("anatomy", AnatomyQuestion, CidUserAnswer, Exam)
GenericViews = GenericViewBase("anatomy", AnatomyQuestion, UserAnswer, Exam)
class ExamClone(ExamCloneMixin, ExamCreate):
+5 -5
View File
@@ -36,25 +36,25 @@ from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.contenttypes.models import ContentType
from physics.models import CidUserAnswer as PhysicsCidUserAnswer, Question
from physics.models import UserAnswer as PhysicsUserAnswer, Question
from physics.models import Exam as PhysicsExam
from physics.models import Question as SbasQuestion
from anatomy.models import CidUserAnswer as AnatomyCidUserAnswer
from anatomy.models import UserAnswer as AnatomyUserAnswer
from anatomy.models import Exam as AnatomyExam
from anatomy.models import AnatomyQuestion
from anatomy.models import Answer as AnatomyAnswer
from rapids.models import CidUserAnswer as RapidsCidUserAnswer
from rapids.models import UserAnswer as RapidsUserAnswer
from rapids.models import Exam as RapidsExam
from rapids.models import Rapid
from rapids.models import Answer as RapidAnswer
from longs.models import CidUserAnswer as LongsCidUserAnswer
from longs.models import UserAnswer as LongsUserAnswer
from longs.models import Exam as LongsExam
from longs.models import Long
from sbas.models import CidUserAnswer as SbasCidUserAnswer
from sbas.models import UserAnswer as SbasUserAnswer
from sbas.models import Exam as SbasExam
from sbas.models import Question as SbasQuestion
+1 -1
View File
@@ -394,7 +394,7 @@ class ExamUserStatus(models.Model):
return f"{self.datetime}: {user} - {self.status} ({self.extra})"
class CidUserAnswerBase(models.Model):
class UserAnswerBase(models.Model):
cid = models.BigIntegerField(
blank=True,
+17 -17
View File
@@ -311,7 +311,7 @@ class ExamViews(View, LoginRequiredMixin):
self.Exam = exam
self.Question = question
self.Answer = answer
self.CidUserAnswer = cid_user_answer
self.UserAnswer = cid_user_answer
self.app_name = app
self.question_type = question_type
self.normalise_score = normalise_score
@@ -855,7 +855,7 @@ class ExamViews(View, LoginRequiredMixin):
questions = exam.exam_questions.all()
cids = self.CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
cids = self.UserAnswer.objects.filter(question__in=questions, exam__id=pk)
# Force a score update
for c in cids:
@@ -1186,7 +1186,7 @@ class ExamViews(View, LoginRequiredMixin):
),
# Prefetch(
# "cid_user_answers",
# queryset=self.CidUserAnswer.objects.filter(score=self.Answer.MarkOptions.UNMARKED, exam__id=pk),
# queryset=self.UserAnswer.objects.filter(score=self.Answer.MarkOptions.UNMARKED, exam__id=pk),
# to_attr="prefetched_unmarked_cid_answers"
# #queryset=self.Answer.objects.filter(),
# ),
@@ -1427,11 +1427,11 @@ class ExamViews(View, LoginRequiredMixin):
)
if uid:
existing_answers = self.CidUserAnswer.objects.filter(
existing_answers = self.UserAnswer.objects.filter(
question__id=answer["qid"], exam__id=eid, user__id=uid
)
else:
existing_answers = self.CidUserAnswer.objects.filter(
existing_answers = self.UserAnswer.objects.filter(
question__id=answer["qid"], exam__id=eid, cid=cid
)
posted_answer = answer["ans"]
@@ -1445,13 +1445,13 @@ class ExamViews(View, LoginRequiredMixin):
if not existing_answers:
if uid:
ans = self.CidUserAnswer(
ans = self.UserAnswer(
answer=posted_answer,
normal=normal,
user=User.objects.get(id=uid),
)
else:
ans = self.CidUserAnswer(
ans = self.UserAnswer(
answer=posted_answer, normal=normal, cid=cid
)
@@ -1471,11 +1471,11 @@ class ExamViews(View, LoginRequiredMixin):
case "anatomy":
if not existing_answers:
if uid:
ans = self.CidUserAnswer(
ans = self.UserAnswer(
answer=posted_answer, user=User.objects.get(id=uid)
)
else:
ans = self.CidUserAnswer(answer=posted_answer, cid=cid)
ans = self.UserAnswer(answer=posted_answer, cid=cid)
ans.question_id = answer["qid"]
ans.exam_id = eid
@@ -1493,9 +1493,9 @@ class ExamViews(View, LoginRequiredMixin):
# If the user answer does not exist
if not existing_answers:
if uid:
ans = self.CidUserAnswer(user=User.objects.get(id=uid))
ans = self.UserAnswer(user=User.objects.get(id=uid))
else:
ans = self.CidUserAnswer(cid=cid)
ans = self.UserAnswer(cid=cid)
ans.question_id = answer["qid"]
ans.exam_id = eid
@@ -1527,7 +1527,7 @@ class ExamViews(View, LoginRequiredMixin):
n = n + 1
# print(CidUserAnswer.objects.filter(exam__id=q["eid"]))
# print(UserAnswer.objects.filter(exam__id=q["eid"]))
# print(request.urlencode())
exam_type, exam_id = request.POST.get("eid").split("/")
@@ -1747,7 +1747,7 @@ class ExamViews(View, LoginRequiredMixin):
exam.exam_questions.all()
) # .prefetch_related("cid_user_answers", "answers")
# cid_user_answers = list(CidUserAnswer.objects.filter(cid=cid, exam__id=pk).prefetch_related("question"))
# cid_user_answers = list(UserAnswer.objects.filter(cid=cid, exam__id=pk).prefetch_related("question"))
# cid_user_answers_q_map = {}
@@ -1874,8 +1874,8 @@ class ExamViews(View, LoginRequiredMixin):
else:
questions = exam.exam_questions.all().prefetch_related("answers")
# We could prefect the CidUserAnswers.answers here (if we didn't cache them)
cid_user_answers = self.CidUserAnswer.objects.select_related("question").filter(
# We could prefect the UserAnswers.answers here (if we didn't cache them)
cid_user_answers = self.UserAnswer.objects.select_related("question").filter(
question__in=questions, exam__id=pk
)
@@ -2063,9 +2063,9 @@ class ExamViews(View, LoginRequiredMixin):
class GenericViewBase:
def __init__(self, app_name, QuestionObject, CidUserAnswerObject, ExamObject):
def __init__(self, app_name, QuestionObject, UserAnswerObject, ExamObject):
self.question_object = QuestionObject
self.cid_user_answer_object = CidUserAnswerObject
self.cid_user_answer_object = UserAnswerObject
self.exam_object = ExamObject
self.app_name = app_name
+2 -2
View File
@@ -1,5 +1,5 @@
from django.contrib import admin
from .models import AnswerMarks, Long, LongSeries, LongSeriesImage, LongCreationDefault, Exam, CidUserAnswer
from .models import AnswerMarks, Long, LongSeries, LongSeriesImage, LongCreationDefault, Exam, UserAnswer
from django.forms import ModelForm
@@ -16,7 +16,7 @@ from tinymce.widgets import TinyMCE
# admin.site.register(Site)
admin.site.register(LongCreationDefault)
admin.site.register(LongSeriesImage)
admin.site.register(CidUserAnswer)
admin.site.register(UserAnswer)
admin.site.register(AnswerMarks)
+4 -4
View File
@@ -1,6 +1,6 @@
import django_filters
from .models import Long, LongSeries, Exam, CidUserAnswer
from .models import Long, LongSeries, Exam, UserAnswer
from django.contrib.auth.models import User
def get_exams(request):
@@ -53,9 +53,9 @@ class LongSeriesFilter(django_filters.FilterSet):
super(LongSeriesFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
class CidUserAnswerFilter(django_filters.FilterSet):
class UserAnswerFilter(django_filters.FilterSet):
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = (
"cid",
#"normal",
@@ -69,5 +69,5 @@ class CidUserAnswerFilter(django_filters.FilterSet):
def __init__(self, data=None, queryset=None, prefix=None, strict=None, user=None, request=None):
if not request.user.groups.filter(name="long_checker").exists():
queryset = queryset.filter(open_access=True) | queryset.filter(author__id=request.user.id)
super(CidUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
super(UserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
+3 -3
View File
@@ -16,7 +16,7 @@ from longs.models import (
LongSeries,
LongSeriesImage,
LongCreationDefault,
CidUserAnswer,
UserAnswer,
Exam,
)
@@ -34,7 +34,7 @@ from tinymce.widgets import TinyMCE
class LongAnswerForm(ModelForm):
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = (
"answer_observations",
"answer_interpretation",
@@ -46,7 +46,7 @@ class LongAnswerForm(ModelForm):
class MarkLongQuestionSingleForm(ModelForm):
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = ["score"]
@@ -0,0 +1,19 @@
# Generated by Django 4.1.4 on 2023-05-15 10:14
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('longs', '0065_remove_long_condition_remove_long_sign'),
]
operations = [
migrations.RenameModel(
old_name='CidUserAnswer',
new_name='UserAnswer',
),
]
+5 -5
View File
@@ -38,7 +38,7 @@ from generic.models import (
Plane,
Contrast,
QuestionNote,
CidUserAnswerBase,
UserAnswerBase,
UserUserGroup,
)
@@ -753,7 +753,7 @@ class Exam(ExamBase):
@reversion.register
class CidUserAnswer(CidUserAnswerBase):
class UserAnswer(UserAnswerBase):
"""User answers by candidate"""
question = models.ForeignKey(
@@ -824,7 +824,7 @@ class CidUserAnswer(CidUserAnswerBase):
def save(self, *args, **kwargs):
self.clean()
return super(CidUserAnswer, self).save(*args, **kwargs)
return super(UserAnswer, self).save(*args, **kwargs)
def clean(self):
for ans in (
@@ -886,7 +886,7 @@ class CidUserAnswer(CidUserAnswerBase):
@reversion.register
class AnswerMarks(models.Model):
score = models.CharField(max_length=3, choices=CidUserAnswer.ScoreOptions.choices)
score = models.CharField(max_length=3, choices=UserAnswer.ScoreOptions.choices)
mark_reason = models.TextField(
null=True,
@@ -903,7 +903,7 @@ class AnswerMarks(models.Model):
)
user_answer = models.ForeignKey(
CidUserAnswer,
UserAnswer,
related_name="mark",
on_delete=models.SET_NULL,
null=True,
+3 -3
View File
@@ -1,7 +1,7 @@
import django_tables2 as tables
from django_tables2.utils import A
from .models import Long, LongSeries, CidUserAnswer
from .models import Long, LongSeries, UserAnswer
from django.utils.html import format_html
@@ -130,7 +130,7 @@ class LongSeriesTable(tables.Table):
print(self)
return format_html("""<a href="#" onclick="return window.create_popup_window('/longs/series/{}', 'Series')" >Popup</a>""", record.pk)
class CidUserAnswerTable(tables.Table):
class UserAnswerTable(tables.Table):
select = tables.CheckBoxColumn(accessor=("pk"))
delete = tables.LinkColumn(
"longs:user_answer_delete", text="Delete", args=[A("pk")], orderable=False
@@ -140,7 +140,7 @@ class CidUserAnswerTable(tables.Table):
args=[A('pk')],
orderable=False)
class Meta:
model = CidUserAnswer
model = UserAnswer
template_name = "django_tables2/bootstrap4.html"
fields = (
"cid",
+3 -3
View File
@@ -17,7 +17,7 @@ from longs.views import GenericExamViews as LongExamViews
from longs.models import (
AnswerMarks,
CidUserAnswer,
UserAnswer,
Exam,
Examination,
Long as Question,
@@ -342,9 +342,9 @@ def test_exams(db, client):
# Check the answers now exist in the database
if testing_cid_user:
answers = CidUserAnswer.objects.filter(cid=cid_user.cid)
answers = UserAnswer.objects.filter(cid=cid_user.cid)
else:
answers = CidUserAnswer.objects.filter(user=cid_user)
answers = UserAnswer.objects.filter(user=cid_user)
assert answers.count() == 3
+3 -3
View File
@@ -136,15 +136,15 @@ urlpatterns = [
),
path(
"user_answers/",
views.CidUserAnswerTableView.as_view(),
views.UserAnswerTableView.as_view(),
name="user_answer_table_view",
),
path(
"user_answers/<int:pk>", views.CidUserAnswerView.as_view(), name="user_answer_view"
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view"
),
path(
"user_answers/<int:pk>/delete",
views.CidUserAnswerDelete.as_view(),
views.UserAnswerDelete.as_view(),
name="user_answer_delete",
),
path(
+15 -15
View File
@@ -41,10 +41,10 @@ from .models import (
LongSeries,
Examination,
Exam,
CidUserAnswer,
UserAnswer,
)
from .tables import LongTable, LongSeriesTable, CidUserAnswerTable
from .filters import LongFilter, LongSeriesFilter, CidUserAnswerFilter
from .tables import LongTable, LongSeriesTable, UserAnswerTable
from .filters import LongFilter, LongSeriesFilter, UserAnswerFilter
from django_tables2 import SingleTableView, SingleTableMixin
from django_filters.views import FilterView
@@ -831,7 +831,7 @@ def mark_question_overview(request, exam_id, sk):
user_answers = question.cid_user_answers.filter(exam__id=exam_id)
unmarked_count = user_answers.filter(
score=CidUserAnswer.ScoreOptions.UNMARKED
score=UserAnswer.ScoreOptions.UNMARKED
).count()
if exam.double_mark:
@@ -872,7 +872,7 @@ def exam_scores_all(request, pk):
questions = exam.exam_questions.all()
cids = (
CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
UserAnswer.objects.filter(question__in=questions, exam__id=pk)
.order_by("cid")
.values_list("cid", flat=True)
.distinct()
@@ -1115,7 +1115,7 @@ def long_series_order_upload_filename(request, pk):
return redirect("longs:long_series_detail", pk=pk)
GenericExamViews = ExamViews(Exam, Long, None, CidUserAnswer, "longs", "long")
GenericExamViews = ExamViews(Exam, Long, None, UserAnswer, "longs", "long")
class ExamCreate(ExamCreateBase):
model = Exam
@@ -1194,20 +1194,20 @@ def question_json_recreate(request, pk):
return redirect("longs:question_detail", pk=pk)
class CidUserAnswerView(LoginRequiredMixin, DetailView):
model = CidUserAnswer
class UserAnswerView(LoginRequiredMixin, DetailView):
model = UserAnswer
class CidUserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = CidUserAnswer
table_class = CidUserAnswerTable
class UserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = UserAnswer
table_class = UserAnswerTable
template_name = "longs/user_answer_question_view.html"
filterset_class = CidUserAnswerFilter
filterset_class = UserAnswerFilter
class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = UserAnswer
template_name = "user_answer_delete.html"
success_url = reverse_lazy("longs:user_answer_table_view")
@@ -1219,7 +1219,7 @@ def user_answer_delete_multiple(request):
# We could probably delete them all at once....
for id in answer_ids:
CidUserAnswer.objects.get(pk=id).delete()
UserAnswer.objects.get(pk=id).delete()
return JsonResponse({"status": "success"})
return JsonResponse({"status": "error"})
+3 -3
View File
@@ -1,5 +1,5 @@
from anatomy.models import CidUserAnswer
from physics.models import Category, Question, Exam, CidUserAnswer
from anatomy.models import UserAnswer
from physics.models import Category, Question, Exam, UserAnswer
from generic.models import CidUser
from django.contrib import admin
@@ -37,5 +37,5 @@ class ExamAdmin(VersionAdmin, admin.ModelAdmin):
admin.site.register(Category)
admin.site.register(Question, QuestionAdmin)
admin.site.register(Exam, ExamAdmin)
admin.site.register(CidUserAnswer)
admin.site.register(UserAnswer)
+5 -5
View File
@@ -1,8 +1,8 @@
import django_filters
from .models import Category, Question, CidUserAnswer, Exam
from .models import Category, Question, UserAnswer, Exam
#from generic.filters import CidUserAnswerFilter
#from generic.filters import UserAnswerFilter
from django.contrib.auth.models import User
@@ -43,9 +43,9 @@ class QuestionFilter(django_filters.FilterSet):
super(QuestionFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
class CidUserAnswerFilter(django_filters.FilterSet):
class UserAnswerFilter(django_filters.FilterSet):
class Meta:
model= CidUserAnswer
model= UserAnswer
fields = (
"cid",
#"question",
@@ -59,5 +59,5 @@ class CidUserAnswerFilter(django_filters.FilterSet):
def __init__(self, data=None, queryset=None, prefix=None, strict=None, user=None, request=None):
if not request.user.groups.filter(name="physics_checker").exists():
queryset = queryset.filter(author__id=request.user.id)
super(CidUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
super(UserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
+4 -4
View File
@@ -12,7 +12,7 @@ from generic.forms import ExamAuthorFormMixin, ExamFormMixin
from .models import (
Question,
CidUserAnswer,
UserAnswer,
Exam,
)
@@ -20,13 +20,13 @@ from django.contrib.admin.widgets import FilteredSelectMultiple
from django.forms.widgets import RadioSelect, TextInput, Textarea
class CidUserAnswerForm(ModelForm):
class UserAnswerForm(ModelForm):
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = ["a", "b", "c", "d", "e"]
def __init__(self, *args, **kwargs):
super(CidUserAnswerForm, self).__init__(*args, **kwargs)
super(UserAnswerForm, self).__init__(*args, **kwargs)
#self.fields['answer'].required = False
@@ -0,0 +1,19 @@
# Generated by Django 4.1.4 on 2023-05-15 10:14
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('physics', '0027_alter_ciduseranswer_options_alter_ciduseranswer_cid'),
]
operations = [
migrations.RenameModel(
old_name='CidUserAnswer',
new_name='UserAnswer',
),
]
+2 -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, CidUserGroup, ExamBase, ExamUserStatus, QuestionNote, CidUserAnswerBase, UserUserGroup
from generic.models import CidUser, CidUserGroup, ExamBase, ExamUserStatus, QuestionNote, UserAnswerBase, UserUserGroup
import reversion
@@ -182,7 +182,7 @@ class Exam(ExamBase):
@reversion.register
class CidUserAnswer(CidUserAnswerBase):
class UserAnswer(UserAnswerBase):
"""User answers by candidate"""
question = models.ForeignKey(
+4 -4
View File
@@ -2,7 +2,7 @@ from django.utils.safestring import mark_safe
import django_tables2 as tables
from django_tables2.utils import A
from .models import Question, CidUserAnswer
from .models import Question, UserAnswer
from django.utils.html import format_html
@@ -10,7 +10,7 @@ from django.utils.html import format_html
# from easy_thumbnails.exceptions import InvalidImageFormatError
# from generic.tables import CidUserAnswerTable
# from generic.tables import UserAnswerTable
# class ImageColumn(tables.Column):
@@ -75,7 +75,7 @@ class QuestionTable(tables.Table):
return mark_safe(value)
class CidUserAnswerTable(tables.Table):
class UserAnswerTable(tables.Table):
select = tables.CheckBoxColumn(accessor=("pk"))
# delete = tables.LinkColumn(
# "physics:user_answer_delete", text="Delete", args=[A("pk")], orderable=False
@@ -85,7 +85,7 @@ class CidUserAnswerTable(tables.Table):
)
class Meta:
model = CidUserAnswer
model = UserAnswer
template_name = "django_tables2/bootstrap4.html"
fields = (
"cid",
+3 -3
View File
@@ -16,7 +16,7 @@ from bs4 import BeautifulSoup
from physics.views import GenericExamViews as PhysicsExamViews
from physics.models import Category, CidUserAnswer, Exam, Question
from physics.models import Category, UserAnswer, Exam, Question
from generic.models import CidUser, CidUserGroup, UserUserGroup
from rad.test_helpers import AssertNotFound, create_cid_user_and_groups
@@ -541,9 +541,9 @@ def test_exams(db, client):
# answer the final question
if testing_cid_user:
cid_user_answer = CidUserAnswer(question=extra_question, a=True, b=False, c=True, d=False, e=True, cid=cid_user.cid, exam=exam)
cid_user_answer = UserAnswer(question=extra_question, a=True, b=False, c=True, d=False, e=True, cid=cid_user.cid, exam=exam)
else:
cid_user_answer = CidUserAnswer(question=extra_question, a=True, b=False, c=True, d=False, e=True, user=current_user, exam=exam)
cid_user_answer = UserAnswer(question=extra_question, a=True, b=False, c=True, d=False, e=True, user=current_user, exam=exam)
cid_user_answer.save()
cid_exam_scores_res = client.get(
+3 -3
View File
@@ -51,17 +51,17 @@ urlpatterns.extend(
# path("exam/json/<int:pk>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
path(
"user_answers/",
views.CidUserAnswerTableView.as_view(),
views.UserAnswerTableView.as_view(),
name="user_answer_table_view",
),
path(
"user_answers/<int:pk>",
views.CidUserAnswerView.as_view(),
views.UserAnswerView.as_view(),
name="user_answer_view",
),
path(
"user_answers/<int:pk>/delete",
views.CidUserAnswerDelete.as_view(),
views.UserAnswerDelete.as_view(),
name="user_answer_delete",
),
path(
+21 -21
View File
@@ -2,9 +2,9 @@ from django.contrib.contenttypes.models import ContentType
from django.utils import timezone
from generic.models import CidUser
from physics.decorators import user_is_author_or_physics_checker
from physics.filters import QuestionFilter, CidUserAnswerFilter
from physics.filters import QuestionFilter, UserAnswerFilter
from generic.mixins import SuperuserRequiredMixin
from physics.tables import QuestionTable, CidUserAnswerTable
from physics.tables import QuestionTable, UserAnswerTable
from django.shortcuts import render, get_object_or_404, redirect
from django.views.decorators.csrf import csrf_exempt
from django import forms
@@ -32,7 +32,7 @@ from django_filters.views import FilterView
from django_tables2.views import SingleTableMixin
from reversion.views import RevisionMixin
from .models import Question, Category, Exam, CidUserAnswer
from .models import Question, Category, Exam, UserAnswer
from collections import defaultdict
import os
@@ -58,7 +58,7 @@ from rest_framework.pagination import PageNumberPagination
from django.core.exceptions import PermissionDenied
from .forms import CidUserAnswerForm, ExamAuthorForm, ExamForm
from .forms import UserAnswerForm, ExamAuthorForm, ExamForm
from .decorators import (
user_is_author_or_physics_checker,
user_is_exam_author_or_physics_checker,
@@ -214,9 +214,9 @@ def exam_take_overview(request, pk, cid=None, passcode=None):
questions = exam.exam_questions.all()
if cid is not None:
answers = CidUserAnswer.objects.filter(cid=cid, exam=exam)
answers = UserAnswer.objects.filter(cid=cid, exam=exam)
else:
answers = CidUserAnswer.objects.filter(user=request.user, exam=exam)
answers = UserAnswer.objects.filter(user=request.user, exam=exam)
answer_question_map = {}
for ans in answers:
@@ -289,9 +289,9 @@ def exam_take(request, pk, sk, cid=None, passcode=None):
if request.method == "POST":
if answer:
form = CidUserAnswerForm(request.POST, instance=answer)
form = UserAnswerForm(request.POST, instance=answer)
else:
form = CidUserAnswerForm(request.POST)
form = UserAnswerForm(request.POST)
if form.is_valid() and not exam.publish_results:
answer = form.save(commit=False)
@@ -327,7 +327,7 @@ def exam_take(request, pk, sk, cid=None, passcode=None):
elif "goto" in request.POST:
return redirect(take_url, sk=int(request.POST.get("goto")), **kwargs)
else:
form = CidUserAnswerForm(instance=answer)
form = UserAnswerForm(instance=answer)
saved_answer = False
@@ -376,7 +376,7 @@ def exam_take(request, pk, sk, cid=None, passcode=None):
# pass
#
# for qid in questions:
# exiting_answers = CidUserAnswer.objects.filter(
# exiting_answers = UserAnswer.objects.filter(
# question__id=qid, exam__id=answer["eid"], cid=answer["cid"]
# )
#
@@ -387,7 +387,7 @@ def exam_take(request, pk, sk, cid=None, passcode=None):
# e = questions[qid]["e"]
#
# if not exiting_answers:
# ans = CidUserAnswer(a=a, b=b, c=c, d=d, e=e, cid=answer["cid"])
# ans = UserAnswer(a=a, b=b, c=c, d=d, e=e, cid=answer["cid"])
# ans.question_id = qid
# ans.exam_id = answer["eid"]
#
@@ -409,9 +409,9 @@ def exam_take(request, pk, sk, cid=None, passcode=None):
# return True, None
GenericExamViews = ExamViews(Exam, Question, None, CidUserAnswer, "physics", "physics")
GenericExamViews = ExamViews(Exam, Question, None, UserAnswer, "physics", "physics")
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
GenericViews = GenericViewBase("physics", Question, UserAnswer, Exam)
class ExamCreate(ExamCreateBase):
model = Exam
@@ -457,21 +457,21 @@ class QuestionView(
class CidUserAnswerView(AuthorOrCheckerRequiredMixin, LoginRequiredMixin, DetailView):
model = CidUserAnswer
class UserAnswerView(AuthorOrCheckerRequiredMixin, LoginRequiredMixin, DetailView):
model = UserAnswer
class CidUserAnswerTableView(
class UserAnswerTableView(
AuthorOrCheckerRequiredMixin, LoginRequiredMixin, SingleTableMixin, FilterView
):
model = CidUserAnswer
table_class = CidUserAnswerTable
model = UserAnswer
table_class = UserAnswerTable
template_name = "physics/user_answer_question_view.html"
filterset_class = CidUserAnswerFilter
filterset_class = UserAnswerFilter
class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = UserAnswer
template_name = "user_answer_delete.html"
success_url = reverse_lazy("physics:user_answer_table_view")
+1 -1
View File
@@ -47,7 +47,7 @@ router_drf = routers.DefaultRouter()
#)
#router_drf.register(
# r"rapids/user_answer",
# rapid_views.CidUserAnswerViewSet,
# rapid_views.UserAnswerViewSet,
# basename="rapid-question-answers",
#)
#router_drf.register(r"rapids", rapid_views.RapidViewSet, basename="rapid")
+19 -19
View File
@@ -38,26 +38,26 @@ from django.http import Http404, JsonResponse
from django.http import HttpResponseRedirect, HttpResponse
from physics.models import CidUserAnswer as PhysicsCidUserAnswer, Question
from physics.models import UserAnswer as PhysicsUserAnswer, Question
from physics.models import Exam as PhysicsExam
from physics.models import Question as SbasQuestion
from anatomy.models import CidUserAnswer as AnatomyCidUserAnswer
from anatomy.models import UserAnswer as AnatomyUserAnswer
from anatomy.models import Exam as AnatomyExam
from anatomy.models import AnatomyQuestion
from anatomy.models import Answer as AnatomyAnswer
from rad.filters import UserListFilter
from rapids.models import CidUserAnswer as RapidsCidUserAnswer
from rapids.models import UserAnswer as RapidsUserAnswer
from rapids.models import Exam as RapidsExam
from rapids.models import Rapid
from rapids.models import Answer as RapidAnswer
from longs.models import CidUserAnswer as LongsCidUserAnswer
from longs.models import UserAnswer as LongsUserAnswer
from longs.models import Exam as LongsExam
from longs.models import Long
from sbas.models import CidUserAnswer as SbasCidUserAnswer
from sbas.models import UserAnswer as SbasUserAnswer
from sbas.models import Exam as SbasExam
from sbas.models import Question as SbasQuestion
@@ -140,18 +140,18 @@ def user_scores(request):
# questions = exam.exam_questions.all()
EXAM_ANSWER_MAP = {
"physics": (PhysicsCidUserAnswer, PhysicsExam),
"anatomy": (AnatomyCidUserAnswer, AnatomyExam),
"rapids": (RapidsCidUserAnswer, RapidsExam),
"longs": (LongsCidUserAnswer, LongsExam),
"sbas": (SbasCidUserAnswer, SbasExam),
"physics": (PhysicsUserAnswer, PhysicsExam),
"anatomy": (AnatomyUserAnswer, AnatomyExam),
"rapids": (RapidsUserAnswer, RapidsExam),
"longs": (LongsUserAnswer, LongsExam),
"sbas": (SbasUserAnswer, SbasExam),
}
kwargs = {"exam_mode": True, "archive": False}
exams = []
for exam_type in EXAM_ANSWER_MAP:
CidUserAnswer, Exam = EXAM_ANSWER_MAP[exam_type]
exam_answers = CidUserAnswer.objects.filter(user=request.user)
UserAnswer, Exam = EXAM_ANSWER_MAP[exam_type]
exam_answers = UserAnswer.objects.filter(user=request.user)
exam_ids = exam_answers.values_list("exam").distinct()
exams_to_add = Exam.objects.filter(id__in=exam_ids, **kwargs)
if exams_to_add:
@@ -206,18 +206,18 @@ def cid_scores(request, cid, passcode):
# questions = exam.exam_questions.all()
EXAM_ANSWER_MAP = {
"physics": (PhysicsCidUserAnswer, PhysicsExam),
"anatomy": (AnatomyCidUserAnswer, AnatomyExam),
"rapids": (RapidsCidUserAnswer, RapidsExam),
"longs": (LongsCidUserAnswer, LongsExam),
"sbas": (SbasCidUserAnswer, SbasExam),
"physics": (PhysicsUserAnswer, PhysicsExam),
"anatomy": (AnatomyUserAnswer, AnatomyExam),
"rapids": (RapidsUserAnswer, RapidsExam),
"longs": (LongsUserAnswer, LongsExam),
"sbas": (SbasUserAnswer, SbasExam),
}
kwargs = {"exam_mode": True, "archive": False}
exams = []
for exam_type in EXAM_ANSWER_MAP:
CidUserAnswer, Exam = EXAM_ANSWER_MAP[exam_type]
exam_answers = CidUserAnswer.objects.filter(cid=cid)
UserAnswer, Exam = EXAM_ANSWER_MAP[exam_type]
exam_answers = UserAnswer.objects.filter(cid=cid)
exam_ids = exam_answers.values_list("exam").distinct()
exams_to_add = Exam.objects.filter(id__in=exam_ids, **kwargs)
if exams_to_add:
+3 -3
View File
@@ -1,5 +1,5 @@
from django.contrib import admin
from .models import Rapid, RapidImage, Examination, Site, Abnormality, Region, RapidCreationDefault, Answer, Exam, CidUserAnswer
from .models import Rapid, RapidImage, Examination, Site, Abnormality, Region, RapidCreationDefault, Answer, Exam, UserAnswer
from django.forms import ModelForm
@@ -71,11 +71,11 @@ class ExamAdmin(VersionAdmin, admin.ModelAdmin):
admin.site.register(Rapid, RapidAdmin)
admin.site.register(Exam, ExamAdmin)
class CidUserAnswerAdmin(admin.ModelAdmin):
class UserAnswerAdmin(admin.ModelAdmin):
exclude = []
readonly_fields = ["created", "updated"]
admin.site.register(CidUserAnswer, CidUserAnswerAdmin)
admin.site.register(UserAnswer, UserAnswerAdmin)
class RapidImageAdmin(admin.ModelAdmin):
readonly_fields = ('rapid',)
+4 -4
View File
@@ -1,6 +1,6 @@
import django_filters
from .models import Rapid, CidUserAnswer, Exam
from .models import Rapid, UserAnswer, Exam
from django.contrib.auth.models import User
@@ -68,9 +68,9 @@ class RapidFilter(django_filters.FilterSet):
pass
class RapidCidUserAnswerFilter(django_filters.FilterSet):
class RapidUserAnswerFilter(django_filters.FilterSet):
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = (
"cid",
"user",
@@ -95,7 +95,7 @@ class RapidCidUserAnswerFilter(django_filters.FilterSet):
queryset = queryset.filter(open_access=True) | queryset.filter(
author__id=request.user.id
)
super(RapidCidUserAnswerFilter, self).__init__(
super(RapidUserAnswerFilter, self).__init__(
data=data, queryset=queryset, prefix=prefix, request=request
)
pass
+2 -2
View File
@@ -17,7 +17,7 @@ from rapids.models import (
RapidImage,
Region,
Answer,
CidUserAnswer,
UserAnswer,
Exam,
)
@@ -28,7 +28,7 @@ from django.contrib.auth.models import User
class RapidAnswerForm(ModelForm):
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = ("answer",)
@@ -0,0 +1,19 @@
# Generated by Django 4.1.4 on 2023-05-15 10:14
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('rapids', '0062_alter_ciduseranswer_options'),
]
operations = [
migrations.RenameModel(
old_name='CidUserAnswer',
new_name='UserAnswer',
),
]
+9 -9
View File
@@ -34,7 +34,7 @@ from generic.models import (
#Sign,
ExamBase,
QuestionNote,
CidUserAnswerBase,
UserAnswerBase,
UserUserGroup,
)
@@ -769,7 +769,7 @@ class Exam(ExamBase):
@reversion.register
class CidUserAnswer(CidUserAnswerBase):
class UserAnswer(UserAnswerBase):
"""User answers by candidate"""
question = models.ForeignKey(
@@ -830,7 +830,7 @@ class CidUserAnswer(CidUserAnswerBase):
def save(self, *args, **kwargs):
self.clean()
return super(CidUserAnswer, self).save(*args, **kwargs)
return super(UserAnswer, self).save(*args, **kwargs)
def clean(self):
self.score = Answer.MarkOptions.UNMARKED
@@ -885,9 +885,9 @@ class CidUserAnswer(CidUserAnswerBase):
# First step we check that the normal/abnormal states match
if q.normal != self.normal:
if q.normal:
self.callstate = CidUserAnswer.CallStateOptions.OVERCALL
self.callstate = UserAnswer.CallStateOptions.OVERCALL
else:
self.callstate = CidUserAnswer.CallStateOptions.UNDERCALL
self.callstate = UserAnswer.CallStateOptions.UNDERCALL
self.score = Answer.MarkOptions.INCORRECT
self.save()
@@ -895,7 +895,7 @@ class CidUserAnswer(CidUserAnswerBase):
return 0
# If both are normal full marks
elif q.normal and self.normal:
self.callstate = CidUserAnswer.CallStateOptions.CORRECT
self.callstate = UserAnswer.CallStateOptions.CORRECT
self.score = Answer.MarkOptions.CORRECT
self.save()
return 2
@@ -920,13 +920,13 @@ class CidUserAnswer(CidUserAnswerBase):
self.score = marked_ans.status
if marked_ans.status == Answer.MarkOptions.CORRECT:
self.callstate = CidUserAnswer.CallStateOptions.CORRECT
self.callstate = UserAnswer.CallStateOptions.CORRECT
mark = 2
elif marked_ans.status == Answer.MarkOptions.HALF_MARK:
self.callstate = CidUserAnswer.CallStateOptions.PARTIALCALL
self.callstate = UserAnswer.CallStateOptions.PARTIALCALL
mark = 1
elif marked_ans.status == Answer.MarkOptions.INCORRECT:
self.callstate = CidUserAnswer.CallStateOptions.INCORRECTCALL
self.callstate = UserAnswer.CallStateOptions.INCORRECTCALL
mark = 0
self.save()
+3 -3
View File
@@ -2,7 +2,7 @@
from rest_framework import serializers, permissions
from .models import Exam, Answer, Rapid, CidUserAnswer
from .models import Exam, Answer, Rapid, UserAnswer
class ExamSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
@@ -18,12 +18,12 @@ class QuestionAnswerSerializer(serializers.HyperlinkedModelSerializer):
fields = ('id', 'question', 'answer', "answer_compare", "status")
view_name = "rapid-exam"
class CidUserAnswerSerializer(serializers.HyperlinkedModelSerializer):
class UserAnswerSerializer(serializers.HyperlinkedModelSerializer):
exam = serializers.HyperlinkedRelatedField(view_name='rapid-exam-detail',
read_only=True
)
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = ('id', 'question', 'normal', "answer", "answer_compare", "cid", "user", "exam", "created", "updated")
class RapidSerializer(serializers.ModelSerializer):
+3 -3
View File
@@ -1,7 +1,7 @@
import django_tables2 as tables
from django_tables2.utils import A
from .models import Rapid, CidUserAnswer
from .models import Rapid, UserAnswer
from django.utils.html import format_html
@@ -66,7 +66,7 @@ class RapidTable(tables.Table):
**kwargs,
)
class RapidCidUserAnswerTable(tables.Table):
class RapidUserAnswerTable(tables.Table):
select = tables.CheckBoxColumn(accessor=("pk"))
delete = tables.LinkColumn(
"rapids:user_answer_delete", text="Delete", args=[A("pk")], orderable=False
@@ -76,7 +76,7 @@ class RapidCidUserAnswerTable(tables.Table):
args=[A('pk')],
orderable=False)
class Meta:
model = CidUserAnswer
model = UserAnswer
template_name = "django_tables2/bootstrap4.html"
fields = (
"cid",
+3 -3
View File
@@ -15,7 +15,7 @@ from bs4 import BeautifulSoup
from rapids.views import GenericExamViews as RapidExamViews
from rapids.models import Answer, CidUserAnswer, Exam, Examination, Rapid as Question, RapidImage
from rapids.models import Answer, UserAnswer, Exam, Examination, Rapid as Question, RapidImage
from generic.models import CidUser, CidUserGroup, UserUserGroup
@@ -295,9 +295,9 @@ def test_exams(db, client):
# Check the answers now exist in the database
if testing_cid_user:
answers = CidUserAnswer.objects.filter(cid=cid_user.cid)
answers = UserAnswer.objects.filter(cid=cid_user.cid)
else:
answers = CidUserAnswer.objects.filter(user=cid_user)
answers = UserAnswer.objects.filter(user=cid_user)
assert answers.count() == 3
+3 -3
View File
@@ -83,15 +83,15 @@ urlpatterns = [
),
path(
"user_answers/",
views.CidUserAnswerTableView.as_view(),
views.UserAnswerTableView.as_view(),
name="user_answer_table_view",
),
path(
"user_answers/<int:pk>", views.CidUserAnswerView.as_view(), name="user_answer_view"
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view"
),
path(
"user_answers/<int:pk>/delete",
views.CidUserAnswerDelete.as_view(),
views.UserAnswerDelete.as_view(),
name="user_answer_delete",
),
path(
+17 -17
View File
@@ -39,7 +39,7 @@ from .models import (
Examination,
Exam,
Answer,
CidUserAnswer,
UserAnswer,
)
from generic.views import (
@@ -54,8 +54,8 @@ from generic.views import (
from reversion.views import RevisionMixin
from .tables import RapidTable, RapidCidUserAnswerTable
from .filters import RapidFilter, RapidCidUserAnswerFilter
from .tables import RapidTable, RapidUserAnswerTable
from .filters import RapidFilter, RapidUserAnswerFilter
from django_tables2 import SingleTableView, SingleTableMixin
from django_filters.views import FilterView
@@ -86,7 +86,7 @@ from .serializers import (
QuestionAnswerSerializer,
RapidLateralitySerializer,
RapidSerializer,
CidUserAnswerSerializer,
UserAnswerSerializer,
)
from generic.mixins import SuperuserRequiredMixin
@@ -693,7 +693,7 @@ class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
success_url = reverse_lazy("rapids:rapid_view")
GenericExamViews = ExamViews(Exam, Rapid, Answer, CidUserAnswer, "rapids", "rapid", normalise_score=normaliseScore)
GenericExamViews = ExamViews(Exam, Rapid, Answer, UserAnswer, "rapids", "rapid", normalise_score=normaliseScore)
class ExamCreate(ExamCreateBase):
@@ -717,20 +717,20 @@ class ExamAuthorUpdate(
class CidUserAnswerView(LoginRequiredMixin, DetailView):
model = CidUserAnswer
class UserAnswerView(LoginRequiredMixin, DetailView):
model = UserAnswer
class CidUserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = CidUserAnswer
table_class = RapidCidUserAnswerTable
class UserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = UserAnswer
table_class = RapidUserAnswerTable
template_name = "rapids/user_answer_question_view.html"
filterset_class = RapidCidUserAnswerFilter
filterset_class = RapidUserAnswerFilter
class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = UserAnswer
template_name = "user_answer_delete.html"
success_url = reverse_lazy("rapids:user_answer_table_view")
@@ -768,9 +768,9 @@ class ExamViewSet(RevisionMixin, viewsets.ModelViewSet):
# permission_classes = [permissions.IsAuthenticated]
#
#
#class CidUserAnswerViewSet(viewsets.ModelViewSet):
# queryset = CidUserAnswer.objects.all() # .order_by('name')
# serializer_class = CidUserAnswerSerializer
#class UserAnswerViewSet(viewsets.ModelViewSet):
# queryset = UserAnswer.objects.all() # .order_by('name')
# serializer_class = UserAnswerSerializer
# permission_classes = [permissions.IsAuthenticated]
@@ -822,7 +822,7 @@ class ExamViewSet(RevisionMixin, viewsets.ModelViewSet):
# return { "content_type" : content_type,
# "object_id" : pk }
GenericViews = GenericViewBase("rapids", Rapid, CidUserAnswer, Exam)
GenericViews = GenericViewBase("rapids", Rapid, UserAnswer, Exam)
@user_is_author_or_rapid_checker
+3 -3
View File
@@ -1,7 +1,7 @@
from django.contrib import admin
# Register your models here.
from .models import Question, Exam, CidUserAnswer, Category
from .models import Question, Exam, UserAnswer, Category
from django.forms import ModelForm
@@ -55,8 +55,8 @@ class ExamAdmin(VersionAdmin, admin.ModelAdmin):
admin.site.register(Category)
admin.site.register(Question, QuestionAdmin)
admin.site.register(Exam, ExamAdmin)
class CidUserAnswerAdmin(admin.ModelAdmin):
class UserAnswerAdmin(admin.ModelAdmin):
exclude = []
readonly_fields = ["created", "updated"]
admin.site.register(CidUserAnswer, CidUserAnswerAdmin)
admin.site.register(UserAnswer, UserAnswerAdmin)
+5 -5
View File
@@ -1,8 +1,8 @@
import django_filters
from .models import Category, Question, CidUserAnswer, Exam
from .models import Category, Question, UserAnswer, Exam
#from generic.filters import CidUserAnswerFilter
#from generic.filters import UserAnswerFilter
from django.contrib.auth.models import User
@@ -43,9 +43,9 @@ class QuestionFilter(django_filters.FilterSet):
super(QuestionFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
class CidUserAnswerFilter(django_filters.FilterSet):
class UserAnswerFilter(django_filters.FilterSet):
class Meta:
model= CidUserAnswer
model= UserAnswer
fields = (
"cid",
#"question",
@@ -59,5 +59,5 @@ class CidUserAnswerFilter(django_filters.FilterSet):
def __init__(self, data=None, queryset=None, prefix=None, strict=None, user=None, request=None):
if not request.user.groups.filter(name="sba_checker").exists():
queryset = queryset.filter(open_access=True) | queryset.filter(author__id=request.user.id)
super(CidUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
super(UserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
+4 -4
View File
@@ -12,7 +12,7 @@ from generic.forms import ExamAuthorFormMixin, ExamFormMixin
from .models import (
Question,
CidUserAnswer,
UserAnswer,
Exam,
Category
)
@@ -23,13 +23,13 @@ from django.forms.widgets import RadioSelect, TextInput, Textarea
from tinymce.widgets import TinyMCE
class CidUserAnswerForm(ModelForm):
class UserAnswerForm(ModelForm):
class Meta:
model = CidUserAnswer
model = UserAnswer
fields = ["answer"]
def __init__(self, *args, **kwargs):
super(CidUserAnswerForm, self).__init__(*args, **kwargs)
super(UserAnswerForm, self).__init__(*args, **kwargs)
self.fields['answer'].required = False
# This should be made generic?
@@ -0,0 +1,19 @@
# Generated by Django 4.1.4 on 2023-05-15 10:14
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('sbas', '0017_alter_ciduseranswer_options_alter_ciduseranswer_cid'),
]
operations = [
migrations.RenameModel(
old_name='CidUserAnswer',
new_name='UserAnswer',
),
]
+2 -2
View File
@@ -11,7 +11,7 @@ from django.utils.translation import gettext_lazy as _
from sortedm2m.fields import SortedManyToManyField
from generic.models import CidUser, CidUserGroup, ExamBase, ExamUserStatus, QuestionNote, CidUserAnswerBase, UserUserGroup
from generic.models import CidUser, CidUserGroup, ExamBase, ExamUserStatus, QuestionNote, UserAnswerBase, UserUserGroup
import reversion
@@ -205,7 +205,7 @@ class Exam(ExamBase):
@reversion.register
class CidUserAnswer(CidUserAnswerBase):
class UserAnswer(UserAnswerBase):
"""User answers by candidate"""
question = models.ForeignKey(
+4 -4
View File
@@ -2,7 +2,7 @@ from django.utils.safestring import mark_safe
import django_tables2 as tables
from django_tables2.utils import A
from .models import Question, CidUserAnswer
from .models import Question, UserAnswer
from django.utils.html import format_html
@@ -10,7 +10,7 @@ from django.utils.html import format_html
#from easy_thumbnails.exceptions import InvalidImageFormatError
#from generic.tables import CidUserAnswerTable
#from generic.tables import UserAnswerTable
#class ImageColumn(tables.Column):
@@ -69,7 +69,7 @@ class QuestionTable(tables.Table):
return mark_safe(value)
class CidUserAnswerTable(tables.Table):
class UserAnswerTable(tables.Table):
select = tables.CheckBoxColumn(accessor=("pk"))
#delete = tables.LinkColumn(
# "sbas:user_answer_delete", text="Delete", args=[A("pk")], orderable=False
@@ -79,7 +79,7 @@ class CidUserAnswerTable(tables.Table):
args=[A('pk')],
orderable=False)
class Meta:
model = CidUserAnswer
model = UserAnswer
template_name = "django_tables2/bootstrap4.html"
fields = (
"cid",
+3 -3
View File
@@ -50,15 +50,15 @@ urlpatterns = [
# path("exam/json/<int:pk>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
path(
"user_answers/",
views.CidUserAnswerTableView.as_view(),
views.UserAnswerTableView.as_view(),
name="user_answer_table_view",
),
path(
"user_answers/<int:pk>", views.CidUserAnswerView.as_view(), name="user_answer_view"
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view"
),
path(
"user_answers/<int:pk>/delete",
views.CidUserAnswerDelete.as_view(),
views.UserAnswerDelete.as_view(),
name="user_answer_delete",
),
path(
+19 -19
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, ExamAuthorForm, ExamForm
from sbas.forms import UserAnswerForm, ExamAuthorForm, ExamForm
from django.shortcuts import render, get_object_or_404, redirect
from django.views.decorators.csrf import csrf_exempt
from django import forms
@@ -28,7 +28,7 @@ from django.http import Http404, JsonResponse
from django.http import HttpResponseRedirect, HttpResponse
from .models import Question, Category, Exam, CidUserAnswer
from .models import Question, Category, Exam, UserAnswer
from django_tables2 import SingleTableView, SingleTableMixin
from django_filters.views import FilterView
@@ -48,8 +48,8 @@ from rest_framework.pagination import PageNumberPagination
from django.core.exceptions import PermissionDenied
from .tables import QuestionTable, CidUserAnswerTable
from .filters import QuestionFilter, CidUserAnswerFilter
from .tables import QuestionTable, UserAnswerTable
from .filters import QuestionFilter, UserAnswerFilter
from .forms import (
QuestionForm,
@@ -178,7 +178,7 @@ def exam_take_overview(request, pk, cid, passcode):
questions = exam.exam_questions.all()
answers = CidUserAnswer.objects.filter(cid=cid, exam=exam)
answers = UserAnswer.objects.filter(cid=cid, exam=exam)
answer_question_map = {}
for ans in answers:
@@ -234,9 +234,9 @@ def exam_take(request, pk, sk, cid, passcode):
if request.method == "POST":
if answer:
form = CidUserAnswerForm(request.POST, instance=answer)
form = UserAnswerForm(request.POST, instance=answer)
else:
form = CidUserAnswerForm(request.POST)
form = UserAnswerForm(request.POST)
if form.is_valid():
answer = form.save(commit=False)
answer.cid = cid
@@ -261,7 +261,7 @@ def exam_take(request, pk, sk, cid, passcode):
"sbas:exam_take", sk=int(request.POST.get("goto")), **kwargs
)
else:
form = CidUserAnswerForm(instance=answer)
form = UserAnswerForm(instance=answer)
previous = -1
if sk > 0:
@@ -294,7 +294,7 @@ def exam_take(request, pk, sk, cid, passcode):
GenericExamViews = ExamViews(
Exam, Question, None, CidUserAnswer, "sbas", "sbas"
Exam, Question, None, UserAnswer, "sbas", "sbas"
)
@@ -404,20 +404,20 @@ class QuestionClone(QuestionCreateBase):
return initial_data
class CidUserAnswerView(LoginRequiredMixin, DetailView):
model = CidUserAnswer
class UserAnswerView(LoginRequiredMixin, DetailView):
model = UserAnswer
class CidUserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = CidUserAnswer
table_class = CidUserAnswerTable
class UserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = UserAnswer
table_class = UserAnswerTable
template_name = "sbas/user_answer_question_view.html"
filterset_class = CidUserAnswerFilter
filterset_class = UserAnswerFilter
class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = UserAnswer
template_name = "user_answer_delete.html"
success_url = reverse_lazy("sbas:user_answer_table_view")
@@ -429,11 +429,11 @@ class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
#
# # We could probably delete them all at once....
# for id in answer_ids:
# CidUserAnswer.objects.get(pk=id).delete()
# UserAnswer.objects.get(pk=id).delete()
# return JsonResponse({"status": "success"})
GenericViews = GenericViewBase("sbas", Question, CidUserAnswer, Exam)
GenericViews = GenericViewBase("sbas", Question, UserAnswer, Exam)
class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):