From 710aa1f93868c21e327d134a93e17347e10eb16d Mon Sep 17 00:00:00 2001 From: robo-mop Date: Mon, 20 Feb 2023 18:04:49 +0530 Subject: [PATCH] Add view_duplicates Add a way for admins to see duplicate (hence redundant) students In prehistoric times, students with the same ID were allowed to be created twice This feature allows admins to see obsolete Student objects --- swd/main/urls.py | 2 + swd/main/views.py | 64 ++++++++++++++++++++++++++++++ swd/templates/view_duplicates.html | 28 +++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 swd/templates/view_duplicates.html diff --git a/swd/main/urls.py b/swd/main/urls.py index 31ee544b..5b714d6f 100644 --- a/swd/main/urls.py +++ b/swd/main/urls.py @@ -78,4 +78,6 @@ url(r'^admin/get_cor_add', views.get_corr_address, name='get_corr_address'), url(r'^admin/delete_students/',views.delete_students, name='delete_students'), + url(r'^admin/view_duplicates/(?P\d+)?/?', views.view_duplicates, name='view_duplicates'), + ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/swd/main/views.py b/swd/main/views.py index 23c13f6f..d57f0fe5 100644 --- a/swd/main/views.py +++ b/swd/main/views.py @@ -38,6 +38,70 @@ from calendar import monthrange +@user_passes_test(lambda a: a.is_superuser) +def view_duplicates(request, end_year:str): + """ + Shows duplicate students from year 2000 to the given end_year (default: current year) + URL: admin/view_duplicates/ + """ + students = [] + + # If the end year isn't given, default to current year + if end_year == None: + end_year = datetime.now().year + # Limit end_year to [2000, ] + end_year = max(2000, min(datetime.now().year, int(end_year))) + + years = [2000, int(end_year)+1] + for year in range(*years): + students.extend(Student.objects.filter(bitsId__startswith=str(year))) + + # students -> list of Student objects in the given range of years + + id_dict = {} + duplicate_list = [] + nulls = [] + fields = ['admit', 'bDay'] + for idx, student in enumerate(students): + # If student hasn't been seen before + # Add to set of ids and continue + if not student.bitsId in id_dict: + id_dict[student.bitsId] = idx + continue + + # At this point we know that `student` has been seen before + + s1 = student + s2 = students[id_dict[student.bitsId]] + + # Identify which of s1 and s2 is the inferior duplicate + inferior = None + master = None + for field in fields: + f1 = getattr(s1, field) + f2 = getattr(s2, field) + if f1==None and f2==None: continue + if f1!=None and f2!=None: continue + if f1: + master = s1 + inferior = s2 + break + master = s2 + inferior = s1 + break + if inferior == None: + # Contingency in case somehow both objects have all fields + nulls.append(s1) + else: + duplicate_list.append([master, inferior]) + + # duplicate_list -> list of [master object, inferior object] lists + + return render(request, "view_duplicates.html", { + "students": duplicate_list, + "start_year": 2000, + "end_year": end_year, + }) def noPhD(func): def check(request, *args, **kwargs): diff --git a/swd/templates/view_duplicates.html b/swd/templates/view_duplicates.html new file mode 100644 index 00000000..4c003368 --- /dev/null +++ b/swd/templates/view_duplicates.html @@ -0,0 +1,28 @@ +{% extends 'indexbase.html' %} + +{% block content %} + +
+

Duplicate Students {{ start_year }} - {{ end_year }} ({{ students|length }} results)

+

Put the ending year at the end of the URL (example: /view_duplicates/2014)

+
+ + + + + + + + + + {% for student_master,student_inferior in students %} + + + + + + + {% endfor %} +
More DetailsLess Details (Should be deleted)NameID
{{ student_master.pk }}{{ student_inferior.pk }}{{ student_master.name }}{{ student_master.bitsId }}
+ +{% endblock %} \ No newline at end of file