create base useranswer class

This commit is contained in:
Ross
2023-05-15 11:12:52 +01:00
parent 525373f393
commit 7aa78c2807
33 changed files with 198 additions and 131 deletions
+3 -3
View File
@@ -2,7 +2,7 @@ import django_filters
from .models import AnatomyQuestion, CidUserAnswer, Exam from .models import AnatomyQuestion, CidUserAnswer, Exam
#from generic.filters import UserAnswerFilter #from generic.filters import CidUserAnswerFilter
from django.contrib.auth.models import User from django.contrib.auth.models import User
@@ -46,7 +46,7 @@ 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 AnatomyUserAnswerFilter(django_filters.FilterSet): class AnatomyCidUserAnswerFilter(django_filters.FilterSet):
class Meta: class Meta:
model= CidUserAnswer model= CidUserAnswer
fields = ( fields = (
@@ -63,5 +63,5 @@ class AnatomyUserAnswerFilter(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(AnatomyUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request) super(AnatomyCidUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass pass
@@ -0,0 +1,17 @@
# Generated by Django 4.1.4 on 2023-05-15 10:11
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('anatomy', '0067_alter_anatomyquestion_image'),
]
operations = [
migrations.AlterModelOptions(
name='ciduseranswer',
options={'ordering': ['cid']},
),
]
+2 -11
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, UserUserGroup from generic.models import CidUser, CidUserGroup, ExamUserStatus, Examination, ExamBase, QuestionNote, CidUserAnswerBase, 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(models.Model): class CidUserAnswer(CidUserAnswerBase):
"""User answers by candidate""" """User answers by candidate"""
question = models.ForeignKey( question = models.ForeignKey(
@@ -477,12 +477,6 @@ class CidUserAnswer(models.Model):
answer_compare = models.TextField(max_length=500, blank=True) answer_compare = models.TextField(max_length=500, blank=True)
cid = models.BigIntegerField(
blank=True,
null=True,
help_text="Candidate ID (limitied by BigIntegerField size)",
)
user = models.ForeignKey( user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True, related_name="user_anatomy_user_answers" settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True, related_name="user_anatomy_user_answers"
) )
@@ -492,9 +486,6 @@ class CidUserAnswer(models.Model):
Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True
) )
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
score = models.CharField( score = models.CharField(
max_length=1, max_length=1,
choices=Answer.MarkOptions.choices, choices=Answer.MarkOptions.choices,
+2 -2
View File
@@ -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 UserAnswerTable #from generic.tables import CidUserAnswerTable
class ImageColumn(tables.Column): class ImageColumn(tables.Column):
@@ -64,7 +64,7 @@ class AnatomyQuestionTable(tables.Table):
*args, *args,
**kwargs, **kwargs,
) )
class AnatomyUserAnswerTable(tables.Table): class AnatomyCidUserAnswerTable(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
+3 -3
View File
@@ -73,15 +73,15 @@ urlpatterns = [
), ),
path( path(
"user_answers/", "user_answers/",
views.UserAnswerTableView.as_view(), views.CidUserAnswerTableView.as_view(),
name="user_answer_table_view", name="user_answer_table_view",
), ),
path( path(
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view" "user_answers/<int:pk>", views.CidUserAnswerView.as_view(), name="user_answer_view"
), ),
path( path(
"user_answers/<int:pk>/delete", "user_answers/<int:pk>/delete",
views.UserAnswerDelete.as_view(), views.CidUserAnswerDelete.as_view(),
name="user_answer_delete", name="user_answer_delete",
), ),
path( path(
+12 -12
View File
@@ -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, AnatomyUserAnswerTable from .tables import AnatomyQuestionTable, AnatomyCidUserAnswerTable
from .filters import AnatomyQuestionFilter, AnatomyUserAnswerFilter from .filters import AnatomyQuestionFilter, AnatomyCidUserAnswerFilter
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 = UserAnswer.objects.filter(user=request.user).values_list("question__pk", flat=True) # # answered_questions = CidUserAnswer.objects.filter(user=request.user).values_list("question__pk", flat=True)
# user_answer_data = UserAnswer.objects.filter(user=request.user).values_list( # user_answer_data = CidUserAnswer.objects.filter(user=request.user).values_list(
# "question__pk", "answer", "flagged" # "question__pk", "answer", "flagged"
# ) # )
# # flagged_questions = UserAnswer.objects.filter(user=request.user, flagged=True).values_list("question__pk", flat=True) # # flagged_questions = CidUserAnswer.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) # # flagged_questions I= CidUserAnswer.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 = UserAnswer.objects.filter(user=request.user, question__pk=pk).first() # ans = CidUserAnswer.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}
@@ -737,19 +737,19 @@ GenericExamViews = ExamViews(
) )
class UserAnswerView(SuperuserRequiredMixin, DetailView): class CidUserAnswerView(SuperuserRequiredMixin, DetailView):
model = CidUserAnswer model = CidUserAnswer
class UserAnswerTableView(SuperuserRequiredMixin, SingleTableMixin, FilterView): class CidUserAnswerTableView(SuperuserRequiredMixin, SingleTableMixin, FilterView):
model = CidUserAnswer model = CidUserAnswer
table_class = AnatomyUserAnswerTable table_class = AnatomyCidUserAnswerTable
template_name = "anatomy/user_answer_question_view.html" template_name = "anatomy/user_answer_question_view.html"
filterset_class = AnatomyUserAnswerFilter filterset_class = AnatomyCidUserAnswerFilter
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView): class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer model = CidUserAnswer
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")
+28
View File
@@ -394,6 +394,34 @@ 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):
cid = models.BigIntegerField(
blank=True,
null=True,
help_text="Candidate ID (limitied by BigIntegerField size)",
)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
ordering = ["cid"]
def get_candidate_name(self) -> str:
if self.cid is not None:
return str(self.cid)
else:
return self.user.username
def get_candidate_masked(self) -> str:
if self.cid is not None:
return str(self.cid)
else:
return str(self.user.id)
class NoteType(models.Model): class NoteType(models.Model):
note_type = models.CharField(max_length=200) note_type = models.CharField(max_length=200)
+1 -1
View File
@@ -1527,7 +1527,7 @@ class ExamViews(View, LoginRequiredMixin):
n = n + 1 n = n + 1
# print(UserAnswer.objects.filter(exam__id=q["eid"])) # print(CidUserAnswer.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("/")
+2 -2
View File
@@ -53,7 +53,7 @@ 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 UserAnswerFilter(django_filters.FilterSet): class CidUserAnswerFilter(django_filters.FilterSet):
class Meta: class Meta:
model = CidUserAnswer model = CidUserAnswer
fields = ( fields = (
@@ -69,5 +69,5 @@ class UserAnswerFilter(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(UserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request) super(CidUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass pass
+2 -16
View File
@@ -38,6 +38,7 @@ from generic.models import (
Plane, Plane,
Contrast, Contrast,
QuestionNote, QuestionNote,
CidUserAnswerBase,
UserUserGroup, UserUserGroup,
) )
@@ -752,7 +753,7 @@ class Exam(ExamBase):
@reversion.register @reversion.register
class CidUserAnswer(models.Model): class CidUserAnswer(CidUserAnswerBase):
"""User answers by candidate""" """User answers by candidate"""
question = models.ForeignKey( question = models.ForeignKey(
@@ -812,11 +813,7 @@ class CidUserAnswer(models.Model):
# "AnswerMarks", related_name="user_answer", on_delete=models.SET_NULL, null=True, blank=True # "AnswerMarks", related_name="user_answer", on_delete=models.SET_NULL, null=True, blank=True
# ) # )
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["cid"]
def __str__(self): def __str__(self):
try: try:
@@ -885,17 +882,6 @@ class CidUserAnswer(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return reverse("longs:user_answer_view", kwargs={"pk": self.pk}) return reverse("longs:user_answer_view", kwargs={"pk": self.pk})
def get_candidate_name(self) -> str:
if self.cid is not None:
return str(self.cid)
else:
return self.user.username
def get_candidate_masked(self) -> str:
if self.cid is not None:
return str(self.cid)
else:
return str(self.user.id)
@reversion.register @reversion.register
+1 -1
View File
@@ -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 UserAnswerTable(tables.Table): class CidUserAnswerTable(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
+3 -3
View File
@@ -136,15 +136,15 @@ urlpatterns = [
), ),
path( path(
"user_answers/", "user_answers/",
views.UserAnswerTableView.as_view(), views.CidUserAnswerTableView.as_view(),
name="user_answer_table_view", name="user_answer_table_view",
), ),
path( path(
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view" "user_answers/<int:pk>", views.CidUserAnswerView.as_view(), name="user_answer_view"
), ),
path( path(
"user_answers/<int:pk>/delete", "user_answers/<int:pk>/delete",
views.UserAnswerDelete.as_view(), views.CidUserAnswerDelete.as_view(),
name="user_answer_delete", name="user_answer_delete",
), ),
path( path(
+7 -7
View File
@@ -43,8 +43,8 @@ from .models import (
Exam, Exam,
CidUserAnswer, CidUserAnswer,
) )
from .tables import LongTable, LongSeriesTable, UserAnswerTable from .tables import LongTable, LongSeriesTable, CidUserAnswerTable
from .filters import LongFilter, LongSeriesFilter, UserAnswerFilter from .filters import LongFilter, LongSeriesFilter, CidUserAnswerFilter
from django_tables2 import SingleTableView, SingleTableMixin from django_tables2 import SingleTableView, SingleTableMixin
from django_filters.views import FilterView from django_filters.views import FilterView
@@ -1194,19 +1194,19 @@ def question_json_recreate(request, pk):
return redirect("longs:question_detail", pk=pk) return redirect("longs:question_detail", pk=pk)
class UserAnswerView(LoginRequiredMixin, DetailView): class CidUserAnswerView(LoginRequiredMixin, DetailView):
model = CidUserAnswer model = CidUserAnswer
class UserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView): class CidUserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = CidUserAnswer model = CidUserAnswer
table_class = UserAnswerTable table_class = CidUserAnswerTable
template_name = "longs/user_answer_question_view.html" template_name = "longs/user_answer_question_view.html"
filterset_class = UserAnswerFilter filterset_class = CidUserAnswerFilter
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView): class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer model = CidUserAnswer
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")
+3 -3
View File
@@ -2,7 +2,7 @@ import django_filters
from .models import Category, Question, CidUserAnswer, Exam from .models import Category, Question, CidUserAnswer, Exam
#from generic.filters import UserAnswerFilter #from generic.filters import CidUserAnswerFilter
from django.contrib.auth.models import User from django.contrib.auth.models import User
@@ -43,7 +43,7 @@ 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 UserAnswerFilter(django_filters.FilterSet): class CidUserAnswerFilter(django_filters.FilterSet):
class Meta: class Meta:
model= CidUserAnswer model= CidUserAnswer
fields = ( fields = (
@@ -59,5 +59,5 @@ class UserAnswerFilter(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(UserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request) super(CidUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass pass
@@ -0,0 +1,22 @@
# Generated by Django 4.1.4 on 2023-05-15 10:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('physics', '0026_remove_exam_stats_graph'),
]
operations = [
migrations.AlterModelOptions(
name='ciduseranswer',
options={'ordering': ['cid']},
),
migrations.AlterField(
model_name='ciduseranswer',
name='cid',
field=models.BigIntegerField(blank=True, help_text='Candidate ID (limitied by BigIntegerField size)', null=True),
),
]
+2 -6
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, UserUserGroup from generic.models import CidUser, CidUserGroup, ExamBase, ExamUserStatus, QuestionNote, CidUserAnswerBase, UserUserGroup
import reversion import reversion
@@ -182,7 +182,7 @@ class Exam(ExamBase):
@reversion.register @reversion.register
class CidUserAnswer(models.Model): class CidUserAnswer(CidUserAnswerBase):
"""User answers by candidate""" """User answers by candidate"""
question = models.ForeignKey( question = models.ForeignKey(
@@ -194,8 +194,6 @@ class CidUserAnswer(models.Model):
d = models.BooleanField(blank=False) d = models.BooleanField(blank=False)
e = models.BooleanField(blank=False) e = models.BooleanField(blank=False)
cid = models.IntegerField(blank=True, null=True)
user = models.ForeignKey( user = models.ForeignKey(
settings.AUTH_USER_MODEL, settings.AUTH_USER_MODEL,
on_delete=models.CASCADE, on_delete=models.CASCADE,
@@ -209,8 +207,6 @@ class CidUserAnswer(models.Model):
Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True
) )
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self): def __str__(self):
return "{}/{}/{}".format(self.cid, self.exam, self.question.pk) return "{}/{}/{}".format(self.cid, self.exam, self.question.pk)
+2 -2
View File
@@ -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 UserAnswerTable # from generic.tables import CidUserAnswerTable
# 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 UserAnswerTable(tables.Table): class CidUserAnswerTable(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
+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.UserAnswerTableView.as_view(), views.CidUserAnswerTableView.as_view(),
name="user_answer_table_view", name="user_answer_table_view",
), ),
path( path(
"user_answers/<int:pk>", "user_answers/<int:pk>",
views.UserAnswerView.as_view(), views.CidUserAnswerView.as_view(),
name="user_answer_view", name="user_answer_view",
), ),
path( path(
"user_answers/<int:pk>/delete", "user_answers/<int:pk>/delete",
views.UserAnswerDelete.as_view(), views.CidUserAnswerDelete.as_view(),
name="user_answer_delete", name="user_answer_delete",
), ),
path( path(
+7 -7
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, UserAnswerFilter from physics.filters import QuestionFilter, CidUserAnswerFilter
from generic.mixins import SuperuserRequiredMixin from generic.mixins import SuperuserRequiredMixin
from physics.tables import QuestionTable, UserAnswerTable from physics.tables import QuestionTable, CidUserAnswerTable
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
@@ -457,21 +457,21 @@ class QuestionView(
class UserAnswerView(AuthorOrCheckerRequiredMixin, LoginRequiredMixin, DetailView): class CidUserAnswerView(AuthorOrCheckerRequiredMixin, LoginRequiredMixin, DetailView):
model = CidUserAnswer model = CidUserAnswer
class UserAnswerTableView( class CidUserAnswerTableView(
AuthorOrCheckerRequiredMixin, LoginRequiredMixin, SingleTableMixin, FilterView AuthorOrCheckerRequiredMixin, LoginRequiredMixin, SingleTableMixin, FilterView
): ):
model = CidUserAnswer model = CidUserAnswer
table_class = UserAnswerTable table_class = CidUserAnswerTable
template_name = "physics/user_answer_question_view.html" template_name = "physics/user_answer_question_view.html"
filterset_class = UserAnswerFilter filterset_class = CidUserAnswerFilter
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView): class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer model = CidUserAnswer
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.UserAnswerViewSet, # rapid_views.CidUserAnswerViewSet,
# 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")
+2 -2
View File
@@ -68,7 +68,7 @@ class RapidFilter(django_filters.FilterSet):
pass pass
class RapidUserAnswerFilter(django_filters.FilterSet): class RapidCidUserAnswerFilter(django_filters.FilterSet):
class Meta: class Meta:
model = CidUserAnswer model = CidUserAnswer
fields = ( fields = (
@@ -95,7 +95,7 @@ class RapidUserAnswerFilter(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(RapidUserAnswerFilter, self).__init__( super(RapidCidUserAnswerFilter, self).__init__(
data=data, queryset=queryset, prefix=prefix, request=request data=data, queryset=queryset, prefix=prefix, request=request
) )
pass pass
@@ -0,0 +1,17 @@
# Generated by Django 4.1.4 on 2023-05-15 10:11
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('rapids', '0061_remove_exam_stats_graph'),
]
operations = [
migrations.AlterModelOptions(
name='ciduseranswer',
options={'ordering': ['cid']},
),
]
+2 -9
View File
@@ -34,6 +34,7 @@ from generic.models import (
#Sign, #Sign,
ExamBase, ExamBase,
QuestionNote, QuestionNote,
CidUserAnswerBase,
UserUserGroup, UserUserGroup,
) )
@@ -768,7 +769,7 @@ class Exam(ExamBase):
@reversion.register @reversion.register
class CidUserAnswer(models.Model): class CidUserAnswer(CidUserAnswerBase):
"""User answers by candidate""" """User answers by candidate"""
question = models.ForeignKey( question = models.ForeignKey(
@@ -781,11 +782,6 @@ class CidUserAnswer(models.Model):
answer_compare = models.TextField(max_length=500, blank=True) answer_compare = models.TextField(max_length=500, blank=True)
cid = models.BigIntegerField(
blank=True,
null=True,
help_text="Candidate ID (limitied by BigIntegerField size)",
)
user = models.ForeignKey( user = models.ForeignKey(
settings.AUTH_USER_MODEL, settings.AUTH_USER_MODEL,
@@ -800,9 +796,6 @@ class CidUserAnswer(models.Model):
Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True
) )
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
score = models.CharField( score = models.CharField(
max_length=1, max_length=1,
choices=Answer.MarkOptions.choices, choices=Answer.MarkOptions.choices,
+1 -1
View File
@@ -18,7 +18,7 @@ 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 UserAnswerSerializer(serializers.HyperlinkedModelSerializer): class CidUserAnswerSerializer(serializers.HyperlinkedModelSerializer):
exam = serializers.HyperlinkedRelatedField(view_name='rapid-exam-detail', exam = serializers.HyperlinkedRelatedField(view_name='rapid-exam-detail',
read_only=True read_only=True
) )
+1 -1
View File
@@ -66,7 +66,7 @@ class RapidTable(tables.Table):
**kwargs, **kwargs,
) )
class RapidUserAnswerTable(tables.Table): class RapidCidUserAnswerTable(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
+3 -3
View File
@@ -83,15 +83,15 @@ urlpatterns = [
), ),
path( path(
"user_answers/", "user_answers/",
views.UserAnswerTableView.as_view(), views.CidUserAnswerTableView.as_view(),
name="user_answer_table_view", name="user_answer_table_view",
), ),
path( path(
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view" "user_answers/<int:pk>", views.CidUserAnswerView.as_view(), name="user_answer_view"
), ),
path( path(
"user_answers/<int:pk>/delete", "user_answers/<int:pk>/delete",
views.UserAnswerDelete.as_view(), views.CidUserAnswerDelete.as_view(),
name="user_answer_delete", name="user_answer_delete",
), ),
path( path(
+10 -10
View File
@@ -54,8 +54,8 @@ from generic.views import (
from reversion.views import RevisionMixin from reversion.views import RevisionMixin
from .tables import RapidTable, RapidUserAnswerTable from .tables import RapidTable, RapidCidUserAnswerTable
from .filters import RapidFilter, RapidUserAnswerFilter from .filters import RapidFilter, RapidCidUserAnswerFilter
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,
UserAnswerSerializer, CidUserAnswerSerializer,
) )
from generic.mixins import SuperuserRequiredMixin from generic.mixins import SuperuserRequiredMixin
@@ -717,19 +717,19 @@ class ExamAuthorUpdate(
class UserAnswerView(LoginRequiredMixin, DetailView): class CidUserAnswerView(LoginRequiredMixin, DetailView):
model = CidUserAnswer model = CidUserAnswer
class UserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView): class CidUserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = CidUserAnswer model = CidUserAnswer
table_class = RapidUserAnswerTable table_class = RapidCidUserAnswerTable
template_name = "rapids/user_answer_question_view.html" template_name = "rapids/user_answer_question_view.html"
filterset_class = RapidUserAnswerFilter filterset_class = RapidCidUserAnswerFilter
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView): class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer model = CidUserAnswer
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 UserAnswerViewSet(viewsets.ModelViewSet): #class CidUserAnswerViewSet(viewsets.ModelViewSet):
# queryset = CidUserAnswer.objects.all() # .order_by('name') # queryset = CidUserAnswer.objects.all() # .order_by('name')
# serializer_class = UserAnswerSerializer # serializer_class = CidUserAnswerSerializer
# permission_classes = [permissions.IsAuthenticated] # permission_classes = [permissions.IsAuthenticated]
+3 -3
View File
@@ -2,7 +2,7 @@ import django_filters
from .models import Category, Question, CidUserAnswer, Exam from .models import Category, Question, CidUserAnswer, Exam
#from generic.filters import UserAnswerFilter #from generic.filters import CidUserAnswerFilter
from django.contrib.auth.models import User from django.contrib.auth.models import User
@@ -43,7 +43,7 @@ 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 UserAnswerFilter(django_filters.FilterSet): class CidUserAnswerFilter(django_filters.FilterSet):
class Meta: class Meta:
model= CidUserAnswer model= CidUserAnswer
fields = ( fields = (
@@ -59,5 +59,5 @@ class UserAnswerFilter(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(UserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request) super(CidUserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass pass
@@ -0,0 +1,22 @@
# Generated by Django 4.1.4 on 2023-05-15 10:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sbas', '0016_remove_exam_stats_graph'),
]
operations = [
migrations.AlterModelOptions(
name='ciduseranswer',
options={'ordering': ['cid']},
),
migrations.AlterField(
model_name='ciduseranswer',
name='cid',
field=models.BigIntegerField(blank=True, help_text='Candidate ID (limitied by BigIntegerField size)', null=True),
),
]
+2 -7
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, UserUserGroup from generic.models import CidUser, CidUserGroup, ExamBase, ExamUserStatus, QuestionNote, CidUserAnswerBase, UserUserGroup
import reversion import reversion
@@ -205,7 +205,7 @@ class Exam(ExamBase):
@reversion.register @reversion.register
class CidUserAnswer(models.Model): class CidUserAnswer(CidUserAnswerBase):
"""User answers by candidate""" """User answers by candidate"""
question = models.ForeignKey( question = models.ForeignKey(
@@ -217,8 +217,6 @@ class CidUserAnswer(models.Model):
help_text="The correct answer", help_text="The correct answer",
) )
cid = models.IntegerField(blank=True, null=True)
user = models.ForeignKey( user = models.ForeignKey(
settings.AUTH_USER_MODEL, settings.AUTH_USER_MODEL,
on_delete=models.CASCADE, on_delete=models.CASCADE,
@@ -232,9 +230,6 @@ class CidUserAnswer(models.Model):
Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True
) )
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self): def __str__(self):
return "{}/{}/{}".format(self.cid, self.exam, self.question.pk) return "{}/{}/{}".format(self.cid, self.exam, self.question.pk)
+2 -2
View File
@@ -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 UserAnswerTable #from generic.tables import CidUserAnswerTable
#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 UserAnswerTable(tables.Table): class CidUserAnswerTable(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
+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.UserAnswerTableView.as_view(), views.CidUserAnswerTableView.as_view(),
name="user_answer_table_view", name="user_answer_table_view",
), ),
path( path(
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view" "user_answers/<int:pk>", views.CidUserAnswerView.as_view(), name="user_answer_view"
), ),
path( path(
"user_answers/<int:pk>/delete", "user_answers/<int:pk>/delete",
views.UserAnswerDelete.as_view(), views.CidUserAnswerDelete.as_view(),
name="user_answer_delete", name="user_answer_delete",
), ),
path( path(
+7 -7
View File
@@ -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, UserAnswerTable from .tables import QuestionTable, CidUserAnswerTable
from .filters import QuestionFilter, UserAnswerFilter from .filters import QuestionFilter, CidUserAnswerFilter
from .forms import ( from .forms import (
QuestionForm, QuestionForm,
@@ -404,19 +404,19 @@ class QuestionClone(QuestionCreateBase):
return initial_data return initial_data
class UserAnswerView(LoginRequiredMixin, DetailView): class CidUserAnswerView(LoginRequiredMixin, DetailView):
model = CidUserAnswer model = CidUserAnswer
class UserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView): class CidUserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = CidUserAnswer model = CidUserAnswer
table_class = UserAnswerTable table_class = CidUserAnswerTable
template_name = "sbas/user_answer_question_view.html" template_name = "sbas/user_answer_question_view.html"
filterset_class = UserAnswerFilter filterset_class = CidUserAnswerFilter
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView): class CidUserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer model = CidUserAnswer
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")