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