From 9b06598de583bf278c4e4b10417f394e3f4b5bb3 Mon Sep 17 00:00:00 2001 From: SKairinos Date: Fri, 18 Oct 2024 16:02:22 +0000 Subject: [PATCH 1/4] add buttons --- portal/templates/portal/coding_club.html | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/portal/templates/portal/coding_club.html b/portal/templates/portal/coding_club.html index a3c61885a..00fee2c0f 100644 --- a/portal/templates/portal/coding_club.html +++ b/portal/templates/portal/coding_club.html @@ -86,12 +86,15 @@

Python coding club

-
- {% csrf_token %} - -
+ + Lvl 1: Grass Snakes + + + Lvl 2: Tiger Snakes + + + Lvl 3: Cobra Snakes +
From 1619d54776c39b9663161f8410eeb2b6f64c51a0 Mon Sep 17 00:00:00 2001 From: SKairinos Date: Fri, 18 Oct 2024 16:03:21 +0000 Subject: [PATCH 2/4] fix: download python button packs --- portal/templates/portal/coding_club.html | 1 + 1 file changed, 1 insertion(+) diff --git a/portal/templates/portal/coding_club.html b/portal/templates/portal/coding_club.html index 00fee2c0f..b2c365d3d 100644 --- a/portal/templates/portal/coding_club.html +++ b/portal/templates/portal/coding_club.html @@ -86,6 +86,7 @@

Python coding club

+ Lvl 1: Grass Snakes From 3f5a0c23452be1b47fbee13d854cbe8799ea940d Mon Sep 17 00:00:00 2001 From: SKairinos Date: Tue, 22 Oct 2024 12:34:48 +0000 Subject: [PATCH 3/4] comment out test --- portal/tests/test_daily_activities.py | 59 +++++++++++++-------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/portal/tests/test_daily_activities.py b/portal/tests/test_daily_activities.py index 97e6cee41..082760c4a 100644 --- a/portal/tests/test_daily_activities.py +++ b/portal/tests/test_daily_activities.py @@ -1,4 +1,4 @@ -from datetime import timedelta, datetime +from datetime import datetime, timedelta from common.models import DailyActivity from selenium.webdriver.common.by import By @@ -7,35 +7,34 @@ from portal.tests.base_test import BaseTest +# class TestDailyActivities(BaseTest): +# def test_coding_club_increment(self): -class TestDailyActivities(BaseTest): - def test_coding_club_increment(self): +# # first create dailyActivity one day before datetime.now() +# # to check if it can handle incrementing on different days +# # then check if increments are done on the same day +# old_date = datetime.now() - timedelta(days=1) +# old_daily_activity = DailyActivity(date=old_date) +# old_daily_activity.save() - # first create dailyActivity one day before datetime.now() - # to check if it can handle incrementing on different days - # then check if increments are done on the same day - old_date = datetime.now() - timedelta(days=1) - old_daily_activity = DailyActivity(date=old_date) - old_daily_activity.save() +# for i in range(4): +# # check both buttons +# self.go_to_homepage() +# button_id = "primary_pack" if i < 2 else "python_pack" +# find_out_more_button = WebDriverWait(self.selenium, 10).until( +# EC.element_to_be_clickable((By.ID, "find_out_more")) +# ) +# find_out_more_button.click() - for i in range(4): - # check both buttons - self.go_to_homepage() - button_id = "primary_pack" if i < 2 else "python_pack" - find_out_more_button = WebDriverWait(self.selenium, 10).until( - EC.element_to_be_clickable((By.ID, "find_out_more")) - ) - find_out_more_button.click() - - daily_count_button = WebDriverWait(self.selenium, 10).until( - EC.visibility_of_element_located((By.ID, button_id)) - ) - daily_count_button.click() - # check the old_date is still the same - old_daily_activity = DailyActivity.objects.get(date=old_date) - assert old_daily_activity.primary_coding_club_downloads == 0 - assert old_daily_activity.python_coding_club_downloads == 0 - # check the current_date is incremented to 2 - current_daily_activity = DailyActivity.objects.get(date=datetime.now()) - assert current_daily_activity.primary_coding_club_downloads == 2 - assert current_daily_activity.python_coding_club_downloads == 2 +# daily_count_button = WebDriverWait(self.selenium, 10).until( +# EC.visibility_of_element_located((By.ID, button_id)) +# ) +# daily_count_button.click() +# # check the old_date is still the same +# old_daily_activity = DailyActivity.objects.get(date=old_date) +# assert old_daily_activity.primary_coding_club_downloads == 0 +# assert old_daily_activity.python_coding_club_downloads == 0 +# # check the current_date is incremented to 2 +# current_daily_activity = DailyActivity.objects.get(date=datetime.now()) +# assert current_daily_activity.primary_coding_club_downloads == 2 +# assert current_daily_activity.python_coding_club_downloads == 2 From 5c769fb640da0f5078dbee73a62c3a35e8d7dcdc Mon Sep 17 00:00:00 2001 From: SKairinos Date: Tue, 22 Oct 2024 14:01:21 +0000 Subject: [PATCH 4/4] feedback --- portal/templates/portal/coding_club.html | 24 ++- portal/tests/test_daily_activities.py | 40 ---- portal/views/home.py | 69 ++----- portal/views/teacher/teach.py | 236 ++++++----------------- 4 files changed, 90 insertions(+), 279 deletions(-) delete mode 100644 portal/tests/test_daily_activities.py diff --git a/portal/templates/portal/coding_club.html b/portal/templates/portal/coding_club.html index b2c365d3d..65b226f8a 100644 --- a/portal/templates/portal/coding_club.html +++ b/portal/templates/portal/coding_club.html @@ -87,15 +87,21 @@

Python coding club

- - Lvl 1: Grass Snakes - - - Lvl 2: Tiger Snakes - - - Lvl 3: Cobra Snakes - +
+ + Lvl 1: Grass Snakes + +
+
+ + Lvl 2: Tiger Snakes + +
+
+ + Lvl 3: Cobra Snakes + +
diff --git a/portal/tests/test_daily_activities.py b/portal/tests/test_daily_activities.py deleted file mode 100644 index 082760c4a..000000000 --- a/portal/tests/test_daily_activities.py +++ /dev/null @@ -1,40 +0,0 @@ -from datetime import datetime, timedelta - -from common.models import DailyActivity -from selenium.webdriver.common.by import By -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.support.ui import WebDriverWait - -from portal.tests.base_test import BaseTest - -# class TestDailyActivities(BaseTest): -# def test_coding_club_increment(self): - -# # first create dailyActivity one day before datetime.now() -# # to check if it can handle incrementing on different days -# # then check if increments are done on the same day -# old_date = datetime.now() - timedelta(days=1) -# old_daily_activity = DailyActivity(date=old_date) -# old_daily_activity.save() - -# for i in range(4): -# # check both buttons -# self.go_to_homepage() -# button_id = "primary_pack" if i < 2 else "python_pack" -# find_out_more_button = WebDriverWait(self.selenium, 10).until( -# EC.element_to_be_clickable((By.ID, "find_out_more")) -# ) -# find_out_more_button.click() - -# daily_count_button = WebDriverWait(self.selenium, 10).until( -# EC.visibility_of_element_located((By.ID, button_id)) -# ) -# daily_count_button.click() -# # check the old_date is still the same -# old_daily_activity = DailyActivity.objects.get(date=old_date) -# assert old_daily_activity.primary_coding_club_downloads == 0 -# assert old_daily_activity.python_coding_club_downloads == 0 -# # check the current_date is incremented to 2 -# current_daily_activity = DailyActivity.objects.get(date=datetime.now()) -# assert current_daily_activity.primary_coding_club_downloads == 2 -# assert current_daily_activity.python_coding_club_downloads == 2 diff --git a/portal/views/home.py b/portal/views/home.py index 0dbf2bb2a..47baa59e4 100644 --- a/portal/views/home.py +++ b/portal/views/home.py @@ -33,15 +33,9 @@ ) from portal.strings.coding_club import CODING_CLUB_BANNER from portal.strings.home_learning import HOME_LEARNING_BANNER -from portal.strings.ten_year_map import ( - TEN_YEAR_MAP_BANNER, - TEN_YEAR_MAP_HEADLINE, -) +from portal.strings.ten_year_map import TEN_YEAR_MAP_BANNER, TEN_YEAR_MAP_HEADLINE from portal.templatetags.app_tags import cloud_storage -from portal.views.teacher.teach import ( - DownloadType, - count_student_pack_downloads_click, -) +from portal.views.teacher.teach import DownloadType, count_student_pack_downloads_click LOGGER = logging.getLogger(__name__) @@ -71,15 +65,11 @@ def render_signup_form(request): invalid_form = False teacher_signup_form = TeacherSignupForm(prefix="teacher_signup") - independent_student_signup_form = IndependentStudentSignupForm( - prefix="independent_student_signup" - ) + independent_student_signup_form = IndependentStudentSignupForm(prefix="independent_student_signup") if request.method == "POST": if "teacher_signup-teacher_email" in request.POST: - teacher_signup_form = TeacherSignupForm( - request.POST, prefix="teacher_signup" - ) + teacher_signup_form = TeacherSignupForm(request.POST, prefix="teacher_signup") if not captcha.CAPTCHA_ENABLED: remove_captcha_from_forms(teacher_signup_form) @@ -133,15 +123,11 @@ def process_signup_form(request, data): [email], personalization_values={ "EMAIL": email, - "LOGIN_URL": request.build_absolute_uri( - reverse("teacher_login") - ), + "LOGIN_URL": request.build_absolute_uri(reverse("teacher_login")), }, ) else: - LOGGER.warn( - f"Ratelimit teacher {RATELIMIT_USER_ALREADY_REGISTERED_EMAIL_GROUP}: {email}" - ) + LOGGER.warn(f"Ratelimit teacher {RATELIMIT_USER_ALREADY_REGISTERED_EMAIL_GROUP}: {email}") else: teacher = Teacher.objects.factory( first_name=data["teacher_first_name"], @@ -152,9 +138,7 @@ def process_signup_form(request, data): send_verification_email(request, teacher.user.user, data) - TotalActivity.objects.update( - teacher_registrations=F("teacher_registrations") + 1 - ) + TotalActivity.objects.update(teacher_registrations=F("teacher_registrations") + 1) return render( request, @@ -182,15 +166,11 @@ def process_independent_student_signup_form(request, data): [email], personalization_values={ "EMAIL": email, - "LOGIN_URL": request.build_absolute_uri( - reverse("independent_student_login") - ), + "LOGIN_URL": request.build_absolute_uri(reverse("independent_student_login")), }, ) else: - LOGGER.warning( - f"Ratelimit independent {RATELIMIT_USER_ALREADY_REGISTERED_EMAIL_GROUP}: {email}" - ) + LOGGER.warning(f"Ratelimit independent {RATELIMIT_USER_ALREADY_REGISTERED_EMAIL_GROUP}: {email}") return render( request, "portal/email_verification_needed.html", @@ -208,9 +188,7 @@ def process_independent_student_signup_form(request, data): send_verification_email(request, student.new_user, data, age=age) - TotalActivity.objects.update( - independent_registrations=F("independent_registrations") + 1 - ) + TotalActivity.objects.update(independent_registrations=F("independent_registrations") + 1) return render( request, @@ -221,10 +199,7 @@ def process_independent_student_signup_form(request, data): def is_developer(request): - return ( - hasattr(request.user, "userprofile") - and request.user.userprofile.developer - ) + return hasattr(request.user, "userprofile") and request.user.userprofile.developer def redirect_teacher_to_correct_page(request, teacher): @@ -254,14 +229,10 @@ def home(request): # tests where the first Selenium test passes, but any following test # fails because it cannot find the Maintenance banner instance. try: - maintenance_banner = DynamicElement.objects.get( - name="Maintenance banner" - ) + maintenance_banner = DynamicElement.objects.get(name="Maintenance banner") if maintenance_banner.active: - messages.info( - request, format_html(maintenance_banner.text), extra_tags="safe" - ) + messages.info(request, format_html(maintenance_banner.text), extra_tags="safe") except ObjectDoesNotExist: pass @@ -279,19 +250,13 @@ def home(request): def coding_club(request): - return render( - request, "portal/coding_club.html", {"BANNER": CODING_CLUB_BANNER} - ) + return render(request, "portal/coding_club.html", {"BANNER": CODING_CLUB_BANNER}) def download_student_pack(request, student_pack_type): if request.method == "POST": count_student_pack_downloads_click(int(student_pack_type)) - link = ( - cloud_storage("club_packs/PythonCodingClub.zip") - if DownloadType(int(student_pack_type)) == DownloadType.PYTHON_PACK - else cloud_storage("club_packs/PrimaryCodingClub.zip") - ) + link = cloud_storage("club_packs/PrimaryCodingClub.zip") return redirect(link) @@ -304,9 +269,7 @@ def home_learning(request): def ten_year_map_page(request): - messages.info( - request, "This page is currently under construction.", extra_tags="safe" - ) + messages.info(request, "This page is currently under construction.", extra_tags="safe") return render( request, "portal/ten_year_map.html", diff --git a/portal/views/teacher/teach.py b/portal/views/teacher/teach.py index 66c1b2d68..9edd9971e 100644 --- a/portal/views/teacher/teach.py +++ b/portal/views/teacher/teach.py @@ -1,11 +1,11 @@ import csv import json -import pytz from datetime import datetime, timedelta from enum import Enum from functools import partial, wraps from uuid import uuid4 +import pytz from common.helpers.emails import send_verification_email from common.helpers.generators import ( generate_access_code, @@ -34,12 +34,10 @@ from django.utils import timezone from django.views.decorators.http import require_POST from game.views.level_selection import get_blockly_episodes, get_python_episodes -from portal.views.registration import handle_reset_password_tracking from reportlab.lib.colors import black, red from reportlab.lib.pagesizes import A4 from reportlab.lib.utils import ImageReader from reportlab.pdfgen import canvas -from portal.helpers.ratelimit import clear_ratelimit_cache_for_user from portal.forms.teach import ( BaseTeacherDismissStudentsFormSet, @@ -55,13 +53,13 @@ TeacherMoveStudentsDestinationForm, TeacherSetStudentPass, ) +from portal.helpers.ratelimit import clear_ratelimit_cache_for_user +from portal.views.registration import handle_reset_password_tracking STUDENT_PASSWORD_LENGTH = 6 REMINDER_CARDS_PDF_ROWS = 8 REMINDER_CARDS_PDF_COLUMNS = 1 -REMINDER_CARDS_PDF_WARNING_TEXT = ( - "Please ensure students keep login details in a secure place" -) +REMINDER_CARDS_PDF_WARNING_TEXT = "Please ensure students keep login details in a secure place" @login_required(login_url=reverse_lazy("teacher_login")) @@ -71,9 +69,7 @@ def teacher_onboarding_create_class(request): Onboarding view for creating a class (and organisation if there isn't one, yet) """ teacher = request.user.new_teacher - requests = Student.objects.filter( - pending_class_request__teacher=teacher, new_user__is_active=True - ) + requests = Student.objects.filter(pending_class_request__teacher=teacher, new_user__is_active=True) if not teacher.school: return HttpResponseRedirect(reverse_lazy("onboarding-organisation")) @@ -84,9 +80,7 @@ def teacher_onboarding_create_class(request): created_class = create_class(form, teacher) messages.success( request, - "The class '{className}' has been created successfully.".format( - className=created_class.name - ), + "The class '{className}' has been created successfully.".format(className=created_class.name), ) return HttpResponseRedirect( reverse_lazy( @@ -133,9 +127,7 @@ def process_edit_class(request, access_code, onboarding_done, next_url): """ klass = get_object_or_404(Class, access_code=access_code) teacher = request.user.new_teacher - students = Student.objects.filter( - class_field=klass, new_user__is_active=True - ).order_by("new_user__first_name") + students = Student.objects.filter(class_field=klass, new_user__is_active=True).order_by("new_user__first_name") check_teacher_authorised(request, klass.teacher) @@ -156,9 +148,7 @@ def process_edit_class(request, access_code, onboarding_done, next_url): login_id=hashed_login_id, ) - TotalActivity.objects.update( - student_registrations=F("student_registrations") + 1 - ) + TotalActivity.objects.update(student_registrations=F("student_registrations") + 1) login_url = generate_student_url(request, new_student, login_id) students_info.append( @@ -241,16 +231,12 @@ def teacher_delete_class(request, access_code): # check user authorised to see class check_teacher_authorised(request, klass.teacher) - if Student.objects.filter( - class_field=klass, new_user__is_active=True - ).exists(): + if Student.objects.filter(class_field=klass, new_user__is_active=True).exists(): messages.info( request, "This class still has students, please remove or delete them all before deleting the class.", ) - return HttpResponseRedirect( - reverse_lazy("view_class", kwargs={"access_code": access_code}) - ) + return HttpResponseRedirect(reverse_lazy("view_class", kwargs={"access_code": access_code})) klass.anonymise() @@ -267,9 +253,7 @@ def teacher_delete_students(request, access_code): # get student objects for students to be deleted, confirming they are in the class student_ids = json.loads(request.POST.get("transfer_students", "[]")) - students = [ - get_object_or_404(Student, id=i, class_field=klass) for i in student_ids - ] + students = [get_object_or_404(Student, id=i, class_field=klass) for i in student_ids] def __anonymise(user): # Delete all personal data from inactive user and mark as inactive. @@ -291,9 +275,7 @@ def __anonymise(user): else: # otherwise, just delete student.new_user.delete() - return HttpResponseRedirect( - reverse_lazy("view_class", kwargs={"access_code": access_code}) - ) + return HttpResponseRedirect(reverse_lazy("view_class", kwargs={"access_code": access_code})) @login_required(login_url=reverse_lazy("teacher_login")) @@ -307,9 +289,7 @@ def teacher_edit_class(request, access_code): """ klass = get_object_or_404(Class, access_code=access_code) old_teacher = klass.teacher - other_teachers = Teacher.objects.filter(school=old_teacher.school).exclude( - user=old_teacher.user - ) + other_teachers = Teacher.objects.filter(school=old_teacher.school).exclude(user=old_teacher.user) # check user authorised to see class check_teacher_authorised(request, klass.teacher) @@ -339,9 +319,7 @@ def teacher_edit_class(request, access_code): elif "level_control_submit" in request.POST: level_control_form = ClassLevelControlForm(request.POST) if level_control_form.is_valid(): - return process_level_control_form( - request, klass, blockly_episodes, python_episodes - ) + return process_level_control_form(request, klass, blockly_episodes, python_episodes) elif "class_move_submit" in request.POST: class_move_form = ClassMoveForm(other_teachers, request.POST) if class_move_form.is_valid(): @@ -383,9 +361,7 @@ def process_edit_class_form(request, klass, form): elif hours < 1000: # Setting to number of hours klass.always_accept_requests = False - klass.accept_requests_until = timezone.now() + timedelta( - hours=hours - ) + klass.accept_requests_until = timezone.now() + timedelta(hours=hours) messages.info( request, "Class set successfully to receive requests from external students until " @@ -407,18 +383,12 @@ def process_edit_class_form(request, klass, form): klass.classmates_data_viewable = classmate_progress klass.save() - messages.success( - request, "The class's settings have been changed successfully." - ) + messages.success(request, "The class's settings have been changed successfully.") - return HttpResponseRedirect( - reverse_lazy("view_class", kwargs={"access_code": klass.access_code}) - ) + return HttpResponseRedirect(reverse_lazy("view_class", kwargs={"access_code": klass.access_code})) -def process_level_control_form( - request, klass, blockly_episodes, python_episodes -): +def process_level_control_form(request, klass, blockly_episodes, python_episodes): """ Find the levels that the user wants to lock and lock them for the specific class. :param request: The request sent by the user submitting the form. @@ -429,23 +399,14 @@ def process_level_control_form( """ levels_to_lock_ids = [] - mark_levels_to_lock_in_episodes( - request, blockly_episodes, levels_to_lock_ids - ) - mark_levels_to_lock_in_episodes( - request, python_episodes, levels_to_lock_ids - ) + mark_levels_to_lock_in_episodes(request, blockly_episodes, levels_to_lock_ids) + mark_levels_to_lock_in_episodes(request, python_episodes, levels_to_lock_ids) klass.locked_levels.clear() - [ - klass.locked_levels.add(levels_to_lock_id) - for levels_to_lock_id in levels_to_lock_ids - ] + [klass.locked_levels.add(levels_to_lock_id) for levels_to_lock_id in levels_to_lock_ids] messages.success(request, "Your level preferences have been saved.") - activity_today = DailyActivity.objects.get_or_create( - date=datetime.now().date() - )[0] + activity_today = DailyActivity.objects.get_or_create(date=datetime.now().date())[0] activity_today.level_control_submits += 1 activity_today.save() @@ -468,14 +429,10 @@ def mark_levels_to_lock_in_episodes(request, episodes, levels_to_lock_ids): [ levels_to_lock_ids.append(episode_level["id"]) for episode_level in episode_levels - if str(episode_level["id"]) - not in request.POST.getlist(episode_name) + if str(episode_level["id"]) not in request.POST.getlist(episode_name) ] else: - [ - levels_to_lock_ids.append(episode_level["id"]) - for episode_level in episode_levels - ] + [levels_to_lock_ids.append(episode_level["id"]) for episode_level in episode_levels] def process_move_class_form(request, klass, form): @@ -501,9 +458,7 @@ def teacher_edit_student(request, pk): student = get_object_or_404(Student, id=pk) check_teacher_authorised(request, student.class_field.teacher) - name_form = TeacherEditStudentForm( - student, initial={"name": student.new_user.first_name} - ) + name_form = TeacherEditStudentForm(student, initial={"name": student.new_user.first_name}) password_form = TeacherSetStudentPass() set_password_mode = False @@ -532,9 +487,7 @@ def teacher_edit_student(request, pk): else: password_form = TeacherSetStudentPass(request.POST) if password_form.is_valid(): - return process_reset_password_form( - request, student, password_form - ) + return process_reset_password_form(request, student, password_form) set_password_mode = True return render( @@ -577,9 +530,7 @@ def process_reset_password_form(request, student, password_form): student.new_user.set_password(new_password) student.new_user.save() student.login_id = login_id - clear_ratelimit_cache_for_user( - f"{student.new_user.first_name},{student.class_field.access_code}" - ) + clear_ratelimit_cache_for_user(f"{student.new_user.first_name},{student.class_field.access_code}") student.blocked_time = datetime.now(tz=pytz.utc) - timedelta(days=1) student.save() @@ -613,9 +564,7 @@ def teacher_dismiss_students(request, access_code): # get student objects for students to be dismissed, confirming they are in the class student_ids = json.loads(request.POST.get("transfer_students", "[]")) - students = [ - get_object_or_404(Student, id=i, class_field=klass) for i in student_ids - ] + students = [get_object_or_404(Student, id=i, class_field=klass) for i in student_ids] TeacherDismissStudentsFormSet = formset_factory( wraps(TeacherDismissStudentsForm)(partial(TeacherDismissStudentsForm)), @@ -626,9 +575,7 @@ def teacher_dismiss_students(request, access_code): if is_right_dismiss_form(request): formset = TeacherDismissStudentsFormSet(request.POST) if formset.is_valid(): - return process_dismiss_student_form( - request, formset, klass, access_code - ) + return process_dismiss_student_form(request, formset, klass, access_code) else: initial_data = [ @@ -679,14 +626,10 @@ def process_dismiss_student_form(request, formset, klass, access_code): student.user.save() # log the data - joinrelease = JoinReleaseStudent.objects.create( - student=student, action_type=JoinReleaseStudent.RELEASE - ) + joinrelease = JoinReleaseStudent.objects.create(student=student, action_type=JoinReleaseStudent.RELEASE) joinrelease.save() - send_verification_email( - request, student.new_user, data, school=klass.teacher.school - ) + send_verification_email(request, student.new_user, data, school=klass.teacher.school) if not failed_users: messages.success( @@ -700,9 +643,7 @@ def process_dismiss_student_form(request, formset, klass, access_code): "Please make sure the email has not been registered to another account.", ) - return HttpResponseRedirect( - reverse_lazy("view_class", kwargs={"access_code": access_code}) - ) + return HttpResponseRedirect(reverse_lazy("view_class", kwargs={"access_code": access_code})) @login_required(login_url=reverse_lazy("teacher_login")) @@ -717,9 +658,7 @@ def teacher_class_password_reset(request, access_code): check_teacher_authorised(request, klass.teacher) student_ids = json.loads(request.POST.get("transfer_students", "[]")) - students = [ - get_object_or_404(Student, id=i, class_field=klass) for i in student_ids - ] + students = [get_object_or_404(Student, id=i, class_field=klass) for i in student_ids] students_info = [] handle_reset_password_tracking(request, "SCHOOL_STUDENT", access_code) @@ -741,9 +680,7 @@ def teacher_class_password_reset(request, access_code): student.new_user.set_password(password) student.new_user.save() student.login_id = hashed_login_id - clear_ratelimit_cache_for_user( - f"{student.new_user.first_name},{access_code}" - ) + clear_ratelimit_cache_for_user(f"{student.new_user.first_name},{access_code}") student.blocked_time = datetime.now(tz=pytz.utc) - timedelta(days=1) student.save() @@ -757,9 +694,7 @@ def teacher_class_password_reset(request, access_code): "students_info": students_info, "query_data": json.dumps(students_info), "class_url": request.build_absolute_uri( - reverse( - "student_login", kwargs={"access_code": klass.access_code} - ) + reverse("student_login", kwargs={"access_code": klass.access_code}) ), }, ) @@ -809,37 +744,26 @@ def teacher_move_students_to_class(request, access_code): check_if_move_authorised(request, old_class, new_class) - transfer_students_ids = json.loads( - request.POST.get("transfer_students", "[]") - ) + transfer_students_ids = json.loads(request.POST.get("transfer_students", "[]")) # get student objects for students to be transferred, confirming they are in the old class still - transfer_students = [ - get_object_or_404(Student, id=i, class_field=old_class) - for i in transfer_students_ids - ] + transfer_students = [get_object_or_404(Student, id=i, class_field=old_class) for i in transfer_students_ids] # get new class' students - new_class_students = Student.objects.filter( - class_field=new_class, new_user__is_active=True - ).order_by("new_user__first_name") + new_class_students = Student.objects.filter(class_field=new_class, new_user__is_active=True).order_by( + "new_user__first_name" + ) TeacherMoveStudentDisambiguationFormSet = formset_factory( - wraps(TeacherMoveStudentDisambiguationForm)( - partial(TeacherMoveStudentDisambiguationForm) - ), + wraps(TeacherMoveStudentDisambiguationForm)(partial(TeacherMoveStudentDisambiguationForm)), extra=0, formset=BaseTeacherMoveStudentsDisambiguationFormSet, ) if is_right_move_form(request): - formset = TeacherMoveStudentDisambiguationFormSet( - new_class, request.POST - ) + formset = TeacherMoveStudentDisambiguationFormSet(new_class, request.POST) if formset.is_valid(): - return process_move_students_form( - request, formset, old_class, new_class - ) + return process_move_students_form(request, formset, old_class, new_class) else: # format the students for the form initial_data = [ @@ -850,9 +774,7 @@ def teacher_move_students_to_class(request, access_code): for student in transfer_students ] - formset = TeacherMoveStudentDisambiguationFormSet( - new_class, initial=initial_data - ) + formset = TeacherMoveStudentDisambiguationFormSet(new_class, initial=initial_data) return render( request, @@ -872,9 +794,7 @@ def check_if_move_authorised(request, old_class, new_class): # check teacher has permission to edit old_class and that both classes # are in the same school - if ( - not teacher.is_admin and teacher != old_class.teacher - ) or teacher.school != new_class.teacher.school: + if (not teacher.is_admin and teacher != old_class.teacher) or teacher.school != new_class.teacher.school: raise Http404 @@ -898,14 +818,8 @@ def process_move_students_form(request, formset, old_class, new_class): student.save() student.new_user.save() - messages.success( - request, "The students have been transferred successfully." - ) - return HttpResponseRedirect( - reverse_lazy( - "view_class", kwargs={"access_code": old_class.access_code} - ) - ) + messages.success(request, "The students have been transferred successfully.") + return HttpResponseRedirect(reverse_lazy("view_class", kwargs={"access_code": old_class.access_code})) class DownloadType(Enum): @@ -938,9 +852,7 @@ def teacher_print_reminder_cards(request, access_code): CARD_INNER_HEIGHT = CARD_HEIGHT - CARD_PADDING * 2 - logo_image = ImageReader( - staticfiles_storage.path("portal/img/logo_cfl_reminder_cards.jpg") - ) + logo_image = ImageReader(staticfiles_storage.path("portal/img/logo_cfl_reminder_cards.jpg")) klass = get_object_or_404(Class, access_code=access_code) # Check auth @@ -948,12 +860,8 @@ def teacher_print_reminder_cards(request, access_code): # Use data from the query string if given student_data = get_student_data(request) - student_login_link = request.build_absolute_uri( - reverse("student_login_access_code") - ) - class_login_link = request.build_absolute_uri( - reverse("student_login", kwargs={"access_code": access_code}) - ) + student_login_link = request.build_absolute_uri(reverse("student_login_access_code")) + class_login_link = request.build_absolute_uri(reverse("student_login", kwargs={"access_code": access_code})) # Now draw everything x = 0 @@ -965,17 +873,10 @@ def teacher_print_reminder_cards(request, access_code): if current_student_count % (NUM_X * NUM_Y) == 0: p.setFillColor(red) p.setFont("Helvetica-Bold", 10) - p.drawString( - PAGE_MARGIN, PAGE_MARGIN / 2, REMINDER_CARDS_PDF_WARNING_TEXT - ) + p.drawString(PAGE_MARGIN, PAGE_MARGIN / 2, REMINDER_CARDS_PDF_WARNING_TEXT) left = PAGE_MARGIN + x * CARD_WIDTH + x * INTER_CARD_MARGIN * 2 - bottom = ( - PAGE_HEIGHT - - PAGE_MARGIN - - (y + 1) * CARD_HEIGHT - - y * INTER_CARD_MARGIN - ) + bottom = PAGE_HEIGHT - PAGE_MARGIN - (y + 1) * CARD_HEIGHT - y * INTER_CARD_MARGIN inner_bottom = bottom + CARD_PADDING @@ -995,12 +896,7 @@ def teacher_print_reminder_cards(request, access_code): anchor="w", ) - text_left = ( - left - + INTER_CARD_MARGIN - + (logo_image.getSize()[0] / logo_image.getSize()[1]) - * card_logo_height - ) + text_left = left + INTER_CARD_MARGIN + (logo_image.getSize()[0] / logo_image.getSize()[1]) * card_logo_height # student details p.setFillColor(black) @@ -1023,9 +919,7 @@ def teacher_print_reminder_cards(request, access_code): inner_bottom + CARD_INNER_HEIGHT * 0.3, f"Name: {student['name']}", ) - p.drawString( - text_left, inner_bottom, f"Password: {student['password']}" - ) + p.drawString(text_left, inner_bottom, f"Password: {student['password']}") x = (x + 1) % NUM_X y = compute_show_page_character(p, x, y, NUM_Y) @@ -1044,17 +938,13 @@ def teacher_print_reminder_cards(request, access_code): @user_passes_test(logged_in_as_teacher, login_url=reverse_lazy("teacher_login")) def teacher_download_csv(request, access_code): response = HttpResponse(content_type="text/csv") - response[ - "Content-Disposition" - ] = 'attachment; filename="student_login_urls.csv"' + response["Content-Disposition"] = 'attachment; filename="student_login_urls.csv"' klass = get_object_or_404(Class, access_code=access_code) # Check auth check_teacher_authorised(request, klass.teacher) - class_url = request.build_absolute_uri( - reverse("student_login", kwargs={"access_code": access_code}) - ) + class_url = request.build_absolute_uri(reverse("student_login", kwargs={"access_code": access_code})) # Use data from the query string if given student_data = get_student_data(request) @@ -1062,9 +952,7 @@ def teacher_download_csv(request, access_code): writer = csv.writer(response) writer.writerow([access_code, class_url]) for student in student_data: - writer.writerow( - [student["name"], student["password"], student["login_url"]] - ) + writer.writerow([student["name"], student["password"], student["login_url"]]) count_student_details_click(DownloadType.CSV) @@ -1092,22 +980,16 @@ def compute_show_page_end(p, x, y): def count_student_pack_downloads_click(student_pack_type): - activity_today = DailyActivity.objects.get_or_create( - date=datetime.now().date() - )[0] + activity_today = DailyActivity.objects.get_or_create(date=datetime.now().date())[0] if DownloadType(student_pack_type) == DownloadType.PRIMARY_PACK: activity_today.primary_coding_club_downloads += 1 - elif DownloadType(student_pack_type) == DownloadType.PYTHON_PACK: - activity_today.python_coding_club_downloads += 1 else: raise Exception("Unknown download type") activity_today.save() def count_student_details_click(download_type): - activity_today = DailyActivity.objects.get_or_create( - date=datetime.now().date() - )[0] + activity_today = DailyActivity.objects.get_or_create(date=datetime.now().date())[0] if download_type == DownloadType.CSV: activity_today.csv_click_count += 1