From 40f5ef5c0a9be37af58df7eacbfe7bf90fd1107f Mon Sep 17 00:00:00 2001 From: Struan Donald <struan@exo.org.uk> Date: Tue, 7 May 2024 17:25:16 +0100 Subject: [PATCH] switch to using middleware for setting session details --- ceuk-marking/settings.py | 1 + crowdsourcer/middleware.py | 36 +++++++++++++++++++++++++ crowdsourcer/mixins.py | 28 ------------------- crowdsourcer/views/base.py | 28 +++++++++---------- crowdsourcer/views/marking.py | 15 +++++------ crowdsourcer/views/progress.py | 43 +++++++++++++++--------------- crowdsourcer/views/rightofreply.py | 15 +++++------ crowdsourcer/views/stats.py | 41 +++++++++++++++------------- 8 files changed, 109 insertions(+), 98 deletions(-) create mode 100644 crowdsourcer/middleware.py delete mode 100644 crowdsourcer/mixins.py diff --git a/ceuk-marking/settings.py b/ceuk-marking/settings.py index 0abf9cea..01ea92b3 100644 --- a/ceuk-marking/settings.py +++ b/ceuk-marking/settings.py @@ -83,6 +83,7 @@ "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", + "crowdsourcer.middleware.AddStateMiddleware", ] ROOT_URLCONF = "ceuk-marking.urls" diff --git a/crowdsourcer/middleware.py b/crowdsourcer/middleware.py new file mode 100644 index 00000000..939d299e --- /dev/null +++ b/crowdsourcer/middleware.py @@ -0,0 +1,36 @@ +from crowdsourcer.models import MarkingSession, ResponseType + + +class AddStateMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + response = self.get_response(request) + return response + + def process_view(self, request, view_func, view_args, view_kwargs): + session_name = view_kwargs.get("marking_session", None) + if session_name is not None: + current_session = MarkingSession.objects.filter( + label=session_name, active=True + ).first() + else: + current_session = MarkingSession.objects.filter(active=True).first() + + current_stage = current_session.stage + if current_stage is None: + current_stage = ResponseType.objects.filter(type="First Mark").first() + + request.current_stage = current_stage + request.current_session = current_session + + def process_template_response(self, request, response): + context = response.context_data + + context["marking_session"] = request.current_session + context["sessions"] = MarkingSession.objects.filter(active=True) + + response.context_data = context + + return response diff --git a/crowdsourcer/mixins.py b/crowdsourcer/mixins.py deleted file mode 100644 index f22f0a0c..00000000 --- a/crowdsourcer/mixins.py +++ /dev/null @@ -1,28 +0,0 @@ -from crowdsourcer.models import MarkingSession, ResponseType - - -class CurrentStateMixin: - def setup(self, request, *args, **kwargs): - super().setup(request, *args, **kwargs) - session_name = kwargs.get("marking_session", None) - if session_name is not None: - current_session = MarkingSession.objects.filter( - label=session_name, active=True - ).first() - else: - current_session = MarkingSession.objects.filter(active=True).first() - - current_stage = current_session.stage - if current_stage is None: - current_stage = ResponseType.objects.filter(type="First Mark").first() - - self.current_stage = current_stage - self.current_session = current_session - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - context["marking_session"] = self.current_session - context["sessions"] = MarkingSession.objects.filter(active=True) - - return context diff --git a/crowdsourcer/views/base.py b/crowdsourcer/views/base.py index 01fbb268..f9740645 100644 --- a/crowdsourcer/views/base.py +++ b/crowdsourcer/views/base.py @@ -7,7 +7,6 @@ from django.views.generic import ListView, TemplateView from crowdsourcer.forms import ResponseFormset -from crowdsourcer.mixins import CurrentStateMixin from crowdsourcer.models import ( Assigned, PublicAuthority, @@ -20,7 +19,7 @@ logger = logging.getLogger(__name__) -class BaseQuestionView(CurrentStateMixin, TemplateView): +class BaseQuestionView(TemplateView): model = Response formset = ResponseFormset response_type = "First Mark" @@ -49,7 +48,7 @@ def check_permissions(self): self.request.user, authority=self.kwargs["name"], section=self.kwargs["section_title"], - marking_session=self.current_session, + marking_session=self.request.current_session, current_stage=self.rt, ): raise PermissionDenied @@ -57,7 +56,7 @@ def check_permissions(self): def get_initial_obj(self): self.authority = PublicAuthority.objects.get(name=self.kwargs["name"]) self.questions = Question.objects.filter( - section__marking_session=self.current_session, + section__marking_session=self.request.current_session, section__title=self.kwargs["section_title"], questiongroup=self.authority.questiongroup, how_marked__in=self.how_marked_in, @@ -133,7 +132,7 @@ def get_context_data(self, **kwargs): return context -class BaseSectionAuthorityList(CurrentStateMixin, ListView): +class BaseSectionAuthorityList(ListView): template_name = "crowdsourcer/section_authority_list.html" model = Section context_object_name = "authorities" @@ -155,7 +154,8 @@ def get_queryset(self): return None section = Section.objects.get( - title=self.kwargs["section_title"], marking_session=self.current_session + title=self.kwargs["section_title"], + marking_session=self.request.current_session, ) questions = Question.objects.filter(section=section, how_marked__in=self.types) @@ -175,7 +175,7 @@ def get_queryset(self): question_list, self.kwargs["section_title"], self.request.user, - self.current_session, + self.request.current_session, assigned=assigned, question_types=self.types, response_type=this_stage, @@ -192,7 +192,7 @@ def get_context_data(self, **kwargs): return context -class BaseAllSectionProgressView(CurrentStateMixin, UserPassesTestMixin, ListView): +class BaseAllSectionProgressView(UserPassesTestMixin, ListView): template_name = "crowdsourcer/all_section_progress.html" model = Section context_object_name = "sections" @@ -204,7 +204,7 @@ def test_func(self): return self.request.user.is_superuser def get_queryset(self): - return Section.objects.filter(marking_session=self.current_session) + return Section.objects.filter(marking_session=self.request.current_session) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -221,7 +221,7 @@ def get_context_data(self, **kwargs): question_list, section.title, self.request.user, - self.current_session, + self.request.current_session, question_types=self.types, response_type=rt, ).distinct() @@ -246,7 +246,7 @@ def get_context_data(self, **kwargs): } assigned = Section.objects.filter( - marking_session=self.current_session + marking_session=self.request.current_session ).annotate( num_authorities=Subquery( Assigned.objects.filter(section=OuterRef("pk"), response_type=rt) @@ -266,7 +266,7 @@ def get_context_data(self, **kwargs): return context -class BaseSectionProgressView(CurrentStateMixin, UserPassesTestMixin, ListView): +class BaseSectionProgressView(UserPassesTestMixin, ListView): template_name = "crowdsourcer/section_progress.html" model = Section context_object_name = "sections" @@ -291,7 +291,7 @@ def get_context_data(self, **kwargs): question_list, section.title, self.request.user, - self.current_session, + self.request.current_session, question_types=self.types, response_type=rt, ) @@ -332,7 +332,7 @@ def get_context_data(self, **kwargs): return context -class BaseAuthorityAssignmentView(CurrentStateMixin, UserPassesTestMixin, ListView): +class BaseAuthorityAssignmentView(UserPassesTestMixin, ListView): template_name = "crowdsourcer/authorities_assigned.html" model = PublicAuthority context_object_name = "authorities" diff --git a/crowdsourcer/views/marking.py b/crowdsourcer/views/marking.py index 2e4a2149..ae94386b 100644 --- a/crowdsourcer/views/marking.py +++ b/crowdsourcer/views/marking.py @@ -4,7 +4,6 @@ from django.urls import reverse from django.views.generic import ListView, TemplateView -from crowdsourcer.mixins import CurrentStateMixin from crowdsourcer.models import ( Assigned, MarkingSession, @@ -25,7 +24,7 @@ class PrivacyPolicyView(TemplateView): template_name = "crowdsourcer/privacy.html" -class OverviewView(CurrentStateMixin, ListView): +class OverviewView(ListView): template_name = "crowdsourcer/assignments.html" model = Assigned context_object_name = "assignments" @@ -43,7 +42,7 @@ def dispatch(self, request, *args, **kwargs): sessions = marker.marking_session.filter(active=True).all() if len(sessions) == 1: session = marker.marking_session.first() - if self.current_session != session: + if self.request.current_session != session: url = reverse( "session_urls:home", kwargs={"marking_session": session.label} ) @@ -63,13 +62,13 @@ def dispatch(self, request, *args, **kwargs): elif marker.response_type.type == "Right of Reply": if Assigned.objects.filter(user=user).exists(): count = Assigned.objects.filter( - user=user, marking_session=self.current_session + user=user, marking_session=self.request.current_session ).count() # however if they only have a single assignment still skip the # assignments screen if count == 1: assignment = Assigned.objects.filter( - user=user, marking_session=self.current_session + user=user, marking_session=self.request.current_session ).first() url = reverse( "authority_ror_sections", @@ -108,7 +107,7 @@ def get_queryset(self): qs = qs.filter(user__is_active=True) - qs = qs.filter(marking_session=self.current_session) + qs = qs.filter(marking_session=self.request.current_session) return qs def get_context_data(self, **kwargs): @@ -127,7 +126,7 @@ def get_context_data(self, **kwargs): ) types = Question.VOLUNTEER_TYPES - if self.current_stage.type == "Audit": + if self.request.current_stage.type == "Audit": types = ["volunteer", "national_volunteer", "foi"] first_mark = ResponseType.objects.get(type="First Mark") @@ -154,7 +153,7 @@ def get_context_data(self, **kwargs): question_list, assignment.section.title, assignment.user, - self.current_session, + self.request.current_session, ] if assignment.authority_id is not None: authorities = Assigned.objects.filter( diff --git a/crowdsourcer/views/progress.py b/crowdsourcer/views/progress.py index ee295d2b..96df2a6a 100644 --- a/crowdsourcer/views/progress.py +++ b/crowdsourcer/views/progress.py @@ -8,7 +8,6 @@ from django.http import HttpResponse from django.views.generic import ListView -from crowdsourcer.mixins import CurrentStateMixin from crowdsourcer.models import ( Assigned, Marker, @@ -51,7 +50,7 @@ class SectionProgressView(BaseSectionProgressView): pass -class BaseAllAuthorityProgressView(CurrentStateMixin, UserPassesTestMixin, ListView): +class BaseAllAuthorityProgressView(UserPassesTestMixin, ListView): template_name = "crowdsourcer/all_authority_progress.html" model = PublicAuthority context_object_name = "authorities" @@ -132,7 +131,7 @@ class AllAuthorityProgressView(BaseAllAuthorityProgressView): pass -class BaseAuthorityProgressView(CurrentStateMixin, UserPassesTestMixin, ListView): +class BaseAuthorityProgressView(UserPassesTestMixin, ListView): template_name = "crowdsourcer/authority_progress.html" model = Section context_object_name = "sections" @@ -144,7 +143,7 @@ def test_func(self): return self.request.user.is_superuser def get_queryset(self): - return Section.objects.filter(marking_session=self.current_session) + return Section.objects.filter(marking_session=self.request.current_session) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -209,7 +208,7 @@ class AuthorityProgressView(BaseAuthorityProgressView): pass -class VolunteerProgressView(CurrentStateMixin, UserPassesTestMixin, ListView): +class VolunteerProgressView(UserPassesTestMixin, ListView): template_name = "crowdsourcer/volunteer_progress.html" model = Section context_object_name = "sections" @@ -221,9 +220,9 @@ def get_queryset(self): user = User.objects.get(id=self.kwargs["id"]) sections = Section.objects.filter( - marking_session=self.current_session, + marking_session=self.request.current_session, id__in=Assigned.objects.filter( - user=user, response_type=self.current_stage + user=user, response_type=self.request.current_stage ).values_list("section", flat=True), ) @@ -238,12 +237,12 @@ def get_context_data(self, **kwargs): types = Question.VOLUNTEER_TYPES - if self.current_stage.type == "Audit": + if self.request.current_stage.type == "Audit": types = ["volunteer", "national_volunteer", "foi"] for section in sections: assigned = Assigned.objects.filter( - user=user, section=section, response_type=self.current_stage + user=user, section=section, response_type=self.request.current_stage ).values_list("authority", flat=True) authorities = ( @@ -265,7 +264,7 @@ def get_context_data(self, **kwargs): Response.objects.filter( question__section=section, authority=OuterRef("pk"), - response_type=self.current_stage, + response_type=self.request.current_stage, ) .exclude(id__in=Response.null_responses()) .values("authority") @@ -305,9 +304,9 @@ def get_context_data(self, **kwargs): } ) - if self.current_stage.type == "First Mark": + if self.request.current_stage.type == "First Mark": authority_url_name = "authority_question_edit" - elif self.current_stage.type == "Audit": + elif self.request.current_stage.type == "Audit": authority_url_name = "authority_audit" context["user"] = user @@ -323,7 +322,7 @@ def test_func(self): return self.request.user.is_superuser def get_queryset(self): - return Assigned.objects.filter(marking_session=self.current_session) + return Assigned.objects.filter(marking_session=self.request.current_session) def render_to_response(self, context, **response_kwargs): response = HttpResponse(content_type="text/csv") @@ -367,7 +366,7 @@ class AllAuthorityRoRProgressView(BaseAllAuthorityProgressView): page_title = "Authorities Right of Reply Progress" -class AuthorityLoginReport(CurrentStateMixin, UserPassesTestMixin, ListView): +class AuthorityLoginReport(UserPassesTestMixin, ListView): template_name = "crowdsourcer/authority_login_report.html" model = PublicAuthority context_object_name = "authorities" @@ -383,7 +382,7 @@ def get_queryset(self): Marker.objects.filter( authority=OuterRef("pk"), response_type__type="Right of Reply", - marking_session=self.current_session, + marking_session=self.request.current_session, ) .order_by("-user__last_login") .values("user__last_login")[:1] @@ -391,7 +390,7 @@ def get_queryset(self): multi_has_logged_in=Subquery( Assigned.objects.filter( authority=OuterRef("pk"), - marking_session=self.current_session, + marking_session=self.request.current_session, user__marker__response_type__type="Right of Reply", ) .order_by("-user__last_login") @@ -404,7 +403,7 @@ def get_queryset(self): return authorities -class AllSectionChallengeView(CurrentStateMixin, UserPassesTestMixin, ListView): +class AllSectionChallengeView(UserPassesTestMixin, ListView): template_name = "crowdsourcer/all_section_challenge.html" model = Section context_object_name = "sections" @@ -413,7 +412,7 @@ def test_func(self): return self.request.user.is_superuser def get_queryset(self): - return Section.objects.filter(marking_session=self.current_session) + return Section.objects.filter(marking_session=self.request.current_session) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -430,7 +429,7 @@ def get_context_data(self, **kwargs): question_list, section.title, self.request.user, - self.current_session, + self.request.current_session, response_type=response_types, question_types=types, ) @@ -476,7 +475,7 @@ def get_context_data(self, **kwargs): return context -class AuthorityContactCSVView(CurrentStateMixin, UserPassesTestMixin, ListView): +class AuthorityContactCSVView(UserPassesTestMixin, ListView): context_object_name = "markers" def test_func(self): @@ -485,7 +484,7 @@ def test_func(self): def get_queryset(self): return Marker.objects.filter( response_type__type="Right of Reply", - marking_session=self.current_session, + marking_session=self.request.current_session, ).select_related("user") def get_context_data(self, **kwargs): @@ -503,7 +502,7 @@ def get_context_data(self, **kwargs): } ) assigned = Assigned.objects.filter( - user=marker.user, marking_session=self.current_session + user=marker.user, marking_session=self.request.current_session ).all() if assigned: for assignment in assigned: diff --git a/crowdsourcer/views/rightofreply.py b/crowdsourcer/views/rightofreply.py index 0c6195fe..cff733a5 100644 --- a/crowdsourcer/views/rightofreply.py +++ b/crowdsourcer/views/rightofreply.py @@ -6,7 +6,6 @@ from django.views.generic import ListView from crowdsourcer.forms import RORResponseFormset -from crowdsourcer.mixins import CurrentStateMixin from crowdsourcer.models import ( Assigned, Marker, @@ -21,7 +20,7 @@ logger = logging.getLogger(__name__) -class AuthorityRORList(CurrentStateMixin, ListView): +class AuthorityRORList(ListView): template_name = "crowdsourcer/authority_assigned_list.html" model = Assigned context_object_name = "assignments" @@ -51,7 +50,7 @@ def get_queryset(self): return qs -class AuthorityRORSectionList(CurrentStateMixin, ListView): +class AuthorityRORSectionList(ListView): template_name = "crowdsourcer/authority_section_list.html" model = Section context_object_name = "sections" @@ -82,11 +81,11 @@ def get_queryset(self): if authority.type == "COMB": sections = Section.objects.filter( - title__contains="(CA)", marking_session=self.current_session + title__contains="(CA)", marking_session=self.request.current_session ) else: sections = Section.objects.exclude(title__contains="(CA)").filter( - marking_session=self.current_session + marking_session=self.request.current_session ) return sections @@ -111,7 +110,7 @@ def get_context_data(self, **kwargs): question_list, section.title, self.request.user, - self.current_session, + self.request.current_session, [authority.id], ] @@ -166,7 +165,7 @@ def check_permissions(self): or Marker.objects.filter( user=user, response_type=self.rt, - marking_session=self.current_session, + marking_session=self.request.current_session, authority=authority, ).exists() or Assigned.objects.filter( @@ -174,7 +173,7 @@ def check_permissions(self): response_type=self.rt, authority=authority, section__isnull=True, - marking_session=self.current_session, + marking_session=self.request.current_session, ).exists() ): denied = False diff --git a/crowdsourcer/views/stats.py b/crowdsourcer/views/stats.py index fbfcf387..07c05830 100644 --- a/crowdsourcer/views/stats.py +++ b/crowdsourcer/views/stats.py @@ -9,7 +9,6 @@ from django.utils.text import slugify from django.views.generic import ListView, TemplateView -from crowdsourcer.mixins import CurrentStateMixin from crowdsourcer.models import Option, PublicAuthority, Question, Response from crowdsourcer.scoring import ( get_all_question_data, @@ -24,7 +23,7 @@ logger = logging.getLogger(__name__) -class AllMarksBaseCSVView(CurrentStateMixin, UserPassesTestMixin, ListView): +class AllMarksBaseCSVView(UserPassesTestMixin, ListView): context_object_name = "responses" response_type = "First Mark" file_name = "grace_first_mark_scores.csv" @@ -36,7 +35,7 @@ def get_queryset(self): return ( Response.objects.filter( response_type__type=self.response_type, - question__section__marking_session=self.current_session, + question__section__marking_session=self.request.current_session, ) .select_related("question", "authority", "question__section", "option") .order_by( @@ -68,7 +67,9 @@ def get_context_data(self, **kwargs): responses = defaultdict(dict) questions = ( - Question.objects.filter(section__marking_session=self.current_session) + Question.objects.filter( + section__marking_session=self.request.current_session + ) .select_related("section") .order_by("section__title", "number", "number_part") ) @@ -193,7 +194,7 @@ def get_context_data(self, **kwargs): return context -class SelectQuestionView(CurrentStateMixin, UserPassesTestMixin, ListView): +class SelectQuestionView(UserPassesTestMixin, ListView): template_name = "crowdsourcer/stats_select_question.html" context_object_name = "questions" @@ -202,7 +203,9 @@ def test_func(self): def get_queryset(self): return ( - Question.objects.filter(section__marking_session=self.current_session) + Question.objects.filter( + section__marking_session=self.request.current_session + ) .select_related("section") .order_by("section__title", "number", "number_part") ) @@ -221,7 +224,7 @@ def get_context_data(self, **kwargs): return context -class QuestionDataCSVView(CurrentStateMixin, UserPassesTestMixin, ListView): +class QuestionDataCSVView(UserPassesTestMixin, ListView): context_object_name = "responses" response_type = "First Mark" headers = [ @@ -251,7 +254,7 @@ def get_queryset(self): q_number, q_part = re.search(r"(\d+)(\w*)", q).groups() responses = ( Response.objects.filter( - question__section__marking_session=self.current_session, + question__section__marking_session=self.request.current_session, question__section__title=section, question__number=q_number, response_type__type=self.response_type, @@ -345,12 +348,12 @@ def get_response_data(self, response): return data -class BaseScoresView(CurrentStateMixin, UserPassesTestMixin, TemplateView): +class BaseScoresView(UserPassesTestMixin, TemplateView): def test_func(self): return self.request.user.is_superuser def get_scores(self): - self.scoring = get_scoring_object(self.current_session) + self.scoring = get_scoring_object(self.request.current_session) def render_to_response(self, context, **response_kwargs): response = HttpResponse( @@ -499,7 +502,7 @@ def get_context_data(self, **kwargs): return context -class QuestionScoresCSV(CurrentStateMixin, UserPassesTestMixin, ListView): +class QuestionScoresCSV(UserPassesTestMixin, ListView): context_object_name = "options" def test_func(self): @@ -509,7 +512,7 @@ def test_func(self): def get_queryset(self): return ( Option.objects.filter( - question__section__marking_session=self.current_session + question__section__marking_session=self.request.current_session ) .select_related("question", "question__section") .order_by( @@ -524,7 +527,7 @@ def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) scoring = {} - get_section_maxes(scoring, self.current_session) + get_section_maxes(scoring, self.request.current_session) sections = defaultdict(dict) for option in context["options"]: @@ -603,7 +606,7 @@ def render_to_response(self, context, **response_kwargs): return response -class BadResponsesView(CurrentStateMixin, UserPassesTestMixin, ListView): +class BadResponsesView(UserPassesTestMixin, ListView): context_object_name = "responses" template_name = "crowdsourcer/bad_responses.html" @@ -616,7 +619,7 @@ def get_queryset(self): response_type__type="Audit", option__isnull=True, multi_option__isnull=True, - question__section__marking_session=self.current_session, + question__section__marking_session=self.request.current_session, ) .select_related("authority", "question", "question__section") .order_by("authority", "question__section") @@ -625,7 +628,7 @@ def get_queryset(self): return responses -class DuplicateResponsesView(CurrentStateMixin, UserPassesTestMixin, ListView): +class DuplicateResponsesView(UserPassesTestMixin, ListView): context_object_name = "responses" template_name = "crowdsourcer/duplicate_responses.html" @@ -633,7 +636,7 @@ def test_func(self): return self.request.user.is_superuser def get_queryset(self): - return get_duplicate_responses(self.current_session) + return get_duplicate_responses(self.request.current_session) def get_context_data(self, **kwargs): ignore_exacts = self.request.GET.get("ignore_exacts", 0) @@ -641,7 +644,9 @@ def get_context_data(self, **kwargs): duplicates = context["responses"] - exact_duplicates = get_exact_duplicates(duplicates, self.current_session) + exact_duplicates = get_exact_duplicates( + duplicates, self.request.current_session + ) exact_ids = [] for exact in exact_duplicates: