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