diff --git a/anatomy/admin.py b/anatomy/admin.py index 481e3792..2ba4072e 100644 --- a/anatomy/admin.py +++ b/anatomy/admin.py @@ -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) diff --git a/anatomy/filters.py b/anatomy/filters.py index 18a7f8bb..f4ab4416 100644 --- a/anatomy/filters.py +++ b/anatomy/filters.py @@ -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 \ No newline at end of file diff --git a/anatomy/forms.py b/anatomy/forms.py index 8bc274e2..25c083d7 100644 --- a/anatomy/forms.py +++ b/anatomy/forms.py @@ -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",) diff --git a/anatomy/migrations/0069_rename_ciduseranswer_useranswer.py b/anatomy/migrations/0069_rename_ciduseranswer_useranswer.py new file mode 100644 index 00000000..542e18dd --- /dev/null +++ b/anatomy/migrations/0069_rename_ciduseranswer_useranswer.py @@ -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', + ), + ] diff --git a/anatomy/models.py b/anatomy/models.py index 08554c1f..75bb7bc7 100644 --- a/anatomy/models.py +++ b/anatomy/models.py @@ -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: diff --git a/anatomy/tables.py b/anatomy/tables.py index 7f0486d5..122a750c 100644 --- a/anatomy/tables.py +++ b/anatomy/tables.py @@ -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", diff --git a/anatomy/urls.py b/anatomy/urls.py index 5ad76726..77d2ffe6 100644 --- a/anatomy/urls.py +++ b/anatomy/urls.py @@ -73,15 +73,15 @@ urlpatterns = [ ), path( "user_answers/", - views.CidUserAnswerTableView.as_view(), + views.UserAnswerTableView.as_view(), name="user_answer_table_view", ), path( - "user_answers/", views.CidUserAnswerView.as_view(), name="user_answer_view" + "user_answers/", views.UserAnswerView.as_view(), name="user_answer_view" ), path( "user_answers//delete", - views.CidUserAnswerDelete.as_view(), + views.UserAnswerDelete.as_view(), name="user_answer_delete", ), path( diff --git a/anatomy/views.py b/anatomy/views.py index 31149b32..86e1b8e4 100644 --- a/anatomy/views.py +++ b/anatomy/views.py @@ -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): diff --git a/generic/forms.py b/generic/forms.py index dddcd9f7..a0bea1ab 100755 --- a/generic/forms.py +++ b/generic/forms.py @@ -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 diff --git a/generic/models.py b/generic/models.py index d0e2ffa4..b8a98b8b 100644 --- a/generic/models.py +++ b/generic/models.py @@ -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, diff --git a/generic/views.py b/generic/views.py index 20e2dced..7087e228 100644 --- a/generic/views.py +++ b/generic/views.py @@ -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 diff --git a/longs/admin.py b/longs/admin.py index 81510495..3351fd0c 100755 --- a/longs/admin.py +++ b/longs/admin.py @@ -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) diff --git a/longs/filters.py b/longs/filters.py index 4d7004c5..a93cc853 100755 --- a/longs/filters.py +++ b/longs/filters.py @@ -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 \ No newline at end of file diff --git a/longs/forms.py b/longs/forms.py index 1dd1e6f2..261987c6 100755 --- a/longs/forms.py +++ b/longs/forms.py @@ -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"] diff --git a/longs/migrations/0066_rename_ciduseranswer_useranswer.py b/longs/migrations/0066_rename_ciduseranswer_useranswer.py new file mode 100644 index 00000000..5ed210df --- /dev/null +++ b/longs/migrations/0066_rename_ciduseranswer_useranswer.py @@ -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', + ), + ] diff --git a/longs/models.py b/longs/models.py index 27cc4ed6..51a865b4 100644 --- a/longs/models.py +++ b/longs/models.py @@ -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, diff --git a/longs/tables.py b/longs/tables.py index 72e98702..df8c0d95 100755 --- a/longs/tables.py +++ b/longs/tables.py @@ -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("""Popup""", 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", diff --git a/longs/tests/test_longs_exams.py b/longs/tests/test_longs_exams.py index 3620934e..553b5335 100644 --- a/longs/tests/test_longs_exams.py +++ b/longs/tests/test_longs_exams.py @@ -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 diff --git a/longs/urls.py b/longs/urls.py index e30f4b70..895aaef8 100755 --- a/longs/urls.py +++ b/longs/urls.py @@ -136,15 +136,15 @@ urlpatterns = [ ), path( "user_answers/", - views.CidUserAnswerTableView.as_view(), + views.UserAnswerTableView.as_view(), name="user_answer_table_view", ), path( - "user_answers/", views.CidUserAnswerView.as_view(), name="user_answer_view" + "user_answers/", views.UserAnswerView.as_view(), name="user_answer_view" ), path( "user_answers//delete", - views.CidUserAnswerDelete.as_view(), + views.UserAnswerDelete.as_view(), name="user_answer_delete", ), path( diff --git a/longs/views.py b/longs/views.py index 4b8286ee..367cbe97 100755 --- a/longs/views.py +++ b/longs/views.py @@ -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"}) diff --git a/physics/admin.py b/physics/admin.py index 8f34d382..3ed292cd 100644 --- a/physics/admin.py +++ b/physics/admin.py @@ -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) diff --git a/physics/filters.py b/physics/filters.py index be6b1811..266eb45f 100644 --- a/physics/filters.py +++ b/physics/filters.py @@ -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 \ No newline at end of file diff --git a/physics/forms.py b/physics/forms.py index 44096dab..ab099de1 100755 --- a/physics/forms.py +++ b/physics/forms.py @@ -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 diff --git a/physics/migrations/0028_rename_ciduseranswer_useranswer.py b/physics/migrations/0028_rename_ciduseranswer_useranswer.py new file mode 100644 index 00000000..928b4ad3 --- /dev/null +++ b/physics/migrations/0028_rename_ciduseranswer_useranswer.py @@ -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', + ), + ] diff --git a/physics/models.py b/physics/models.py index 88bc78e4..d845fbf0 100644 --- a/physics/models.py +++ b/physics/models.py @@ -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( diff --git a/physics/tables.py b/physics/tables.py index bcbd9c69..c0f7bb29 100644 --- a/physics/tables.py +++ b/physics/tables.py @@ -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", diff --git a/physics/tests/test_physics_exams.py b/physics/tests/test_physics_exams.py index c87d8c1e..d0dcc2c1 100644 --- a/physics/tests/test_physics_exams.py +++ b/physics/tests/test_physics_exams.py @@ -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( diff --git a/physics/urls.py b/physics/urls.py index 7980baa8..37129187 100644 --- a/physics/urls.py +++ b/physics/urls.py @@ -51,17 +51,17 @@ urlpatterns.extend( # path("exam/json//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/", - views.CidUserAnswerView.as_view(), + views.UserAnswerView.as_view(), name="user_answer_view", ), path( "user_answers//delete", - views.CidUserAnswerDelete.as_view(), + views.UserAnswerDelete.as_view(), name="user_answer_delete", ), path( diff --git a/physics/views.py b/physics/views.py index 4369e2bc..13d64ac4 100644 --- a/physics/views.py +++ b/physics/views.py @@ -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") diff --git a/rad/urls.py b/rad/urls.py index a53bb66d..a1e93057 100644 --- a/rad/urls.py +++ b/rad/urls.py @@ -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") diff --git a/rad/views.py b/rad/views.py index 19ca4f0e..e98201a0 100644 --- a/rad/views.py +++ b/rad/views.py @@ -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: diff --git a/rapids/admin.py b/rapids/admin.py index b9f416bb..6fa9b276 100755 --- a/rapids/admin.py +++ b/rapids/admin.py @@ -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',) diff --git a/rapids/filters.py b/rapids/filters.py index d73828fa..c8e9fdd6 100755 --- a/rapids/filters.py +++ b/rapids/filters.py @@ -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 diff --git a/rapids/forms.py b/rapids/forms.py index 090f4a80..d7b1b5a1 100755 --- a/rapids/forms.py +++ b/rapids/forms.py @@ -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",) diff --git a/rapids/migrations/0063_rename_ciduseranswer_useranswer.py b/rapids/migrations/0063_rename_ciduseranswer_useranswer.py new file mode 100644 index 00000000..f75b327b --- /dev/null +++ b/rapids/migrations/0063_rename_ciduseranswer_useranswer.py @@ -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', + ), + ] diff --git a/rapids/models.py b/rapids/models.py index adaa81b3..ccaea215 100644 --- a/rapids/models.py +++ b/rapids/models.py @@ -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() diff --git a/rapids/serializers.py b/rapids/serializers.py index 7a957888..65f7d91e 100644 --- a/rapids/serializers.py +++ b/rapids/serializers.py @@ -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): diff --git a/rapids/tables.py b/rapids/tables.py index a2b3d45e..f8e191b1 100755 --- a/rapids/tables.py +++ b/rapids/tables.py @@ -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", diff --git a/rapids/tests/test_rapids_exams.py b/rapids/tests/test_rapids_exams.py index ade83ad1..b334bf7a 100644 --- a/rapids/tests/test_rapids_exams.py +++ b/rapids/tests/test_rapids_exams.py @@ -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 diff --git a/rapids/urls.py b/rapids/urls.py index 5dc08a11..a8aa8a8a 100755 --- a/rapids/urls.py +++ b/rapids/urls.py @@ -83,15 +83,15 @@ urlpatterns = [ ), path( "user_answers/", - views.CidUserAnswerTableView.as_view(), + views.UserAnswerTableView.as_view(), name="user_answer_table_view", ), path( - "user_answers/", views.CidUserAnswerView.as_view(), name="user_answer_view" + "user_answers/", views.UserAnswerView.as_view(), name="user_answer_view" ), path( "user_answers//delete", - views.CidUserAnswerDelete.as_view(), + views.UserAnswerDelete.as_view(), name="user_answer_delete", ), path( diff --git a/rapids/views.py b/rapids/views.py index cc64af47..ee98f852 100755 --- a/rapids/views.py +++ b/rapids/views.py @@ -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 diff --git a/sbas/admin.py b/sbas/admin.py index a148e642..c08aab60 100644 --- a/sbas/admin.py +++ b/sbas/admin.py @@ -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) \ No newline at end of file +admin.site.register(UserAnswer, UserAnswerAdmin) \ No newline at end of file diff --git a/sbas/filters.py b/sbas/filters.py index e89cb860..71492599 100644 --- a/sbas/filters.py +++ b/sbas/filters.py @@ -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 \ No newline at end of file diff --git a/sbas/forms.py b/sbas/forms.py index 525d1704..f6a2ac07 100755 --- a/sbas/forms.py +++ b/sbas/forms.py @@ -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? diff --git a/sbas/migrations/0018_rename_ciduseranswer_useranswer.py b/sbas/migrations/0018_rename_ciduseranswer_useranswer.py new file mode 100644 index 00000000..8ac861cc --- /dev/null +++ b/sbas/migrations/0018_rename_ciduseranswer_useranswer.py @@ -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', + ), + ] diff --git a/sbas/models.py b/sbas/models.py index e339d1d8..1463a79a 100644 --- a/sbas/models.py +++ b/sbas/models.py @@ -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( diff --git a/sbas/tables.py b/sbas/tables.py index 04311619..da138262 100644 --- a/sbas/tables.py +++ b/sbas/tables.py @@ -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", diff --git a/sbas/urls.py b/sbas/urls.py index 3d726d62..2fb30b1b 100644 --- a/sbas/urls.py +++ b/sbas/urls.py @@ -50,15 +50,15 @@ urlpatterns = [ # path("exam/json//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/", views.CidUserAnswerView.as_view(), name="user_answer_view" + "user_answers/", views.UserAnswerView.as_view(), name="user_answer_view" ), path( "user_answers//delete", - views.CidUserAnswerDelete.as_view(), + views.UserAnswerDelete.as_view(), name="user_answer_delete", ), path( diff --git a/sbas/views.py b/sbas/views.py index 7d6b4033..2a5cce07 100644 --- a/sbas/views.py +++ b/sbas/views.py @@ -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):