diff --git a/cntmanage/flightslot/admin.py b/cntmanage/flightslot/admin.py index 66444bb..59022a9 100644 --- a/cntmanage/flightslot/admin.py +++ b/cntmanage/flightslot/admin.py @@ -9,8 +9,7 @@ from .models.weekpref import WeekPreference from .admins.course_adm import CourseAdmin from .admins.student_adm import StudentAdmin from .admins.mission_adm import MissionProfileAdmin -from .admins.weekpred_adm import WeekPreferenceAdmin -#from .admins.hourbuilding_adm import HourBuilding, HourBuildingInLine +from .admins.weekpref_adm import WeekPreferenceAdmin from django.contrib.admin import AdminSite diff --git a/cntmanage/flightslot/admins/mission_adm.py b/cntmanage/flightslot/admins/mission_adm.py index 52e2b3e..3dafa1d 100644 --- a/cntmanage/flightslot/admins/mission_adm.py +++ b/cntmanage/flightslot/admins/mission_adm.py @@ -34,6 +34,6 @@ class MissionProfileResource(ModelResource): fields = ("mtype", "mnum", "duration") import_id_fields = ("mtype", "mnum") -class MissionProfileAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin): +class MissionProfileAdmin(AdminActionFormsMixin, ImportMixin, admin.ModelAdmin): list_display = ("mtype", "mnum", "notes") list_filter = ("mtype",) diff --git a/cntmanage/flightslot/admins/student_adm.py b/cntmanage/flightslot/admins/student_adm.py index 63b7e90..b1e328a 100644 --- a/cntmanage/flightslot/admins/student_adm.py +++ b/cntmanage/flightslot/admins/student_adm.py @@ -6,16 +6,25 @@ from django.utils.safestring import SafeText from import_export import fields from import_export.admin import ImportMixin +from import_export.tmp_storages import CacheStorage from import_export.resources import ModelResource -from import_export.widgets import CharWidget +from import_export.forms import ConfirmImportForm, ImportForm from django_admin_action_forms import AdminActionFormsMixin, AdminActionForm, action_with_form +from typing import Any, Dict + from ..models.courses import Course from ..models.students import Student from ..custom.colortag import course_color +# Custom import form to select a course for student input +class StudentCustomConfirmImportForm(ConfirmImportForm): + course = forms.ModelChoiceField( + queryset=Course.objects.all(), + required=False) + # Resource Class for Student data import class StudentResource(ModelResource): surname = fields.Field(attribute="surname", column_name="surname") @@ -24,29 +33,38 @@ class StudentResource(ModelResource): phone = fields.Field(attribute="phone", column_name="phone") # Cleanup fields before entering - def before_import_row(self, row: dict[str, str], **kwargs) -> None: - row["name"] = SafeText(row["name"].capitalize().strip()) - row["surname"] = SafeText(row["surname"].capitalize().strip()) + def before_import_row(self, row: Dict[str, str], **kwargs) -> None: + row["name"] = SafeText("-".join(c.capitalize() for c in row["name"].split(" ")).strip()) + row["surname"] = SafeText("-".join(c.capitalize() for c in row["surname"].split(" ")).strip()) row["phone"] = SafeText(row["phone"].replace(" ","")) row["email"] = SafeText(row["email"].lower().strip()) return super().before_import_row(row, **kwargs) + + # If course was addedd as a form kwasrg add it to the student after creation + def after_init_instance(self, instance: Student, new: bool, row: Dict[str, str], **kwargs: Dict[str, Any]): + if hasattr(kwargs, "course") and isinstance(kwargs["course"], Course): + instance.course = kwargs["course"] class Meta: model = Student skip_unchanged = True report_skipped = True - fields = ("surname", "name", "email", "phone") - import_id_fields = ("email", "phone") + fields = ("surname", "name", "email", "phone",) + import_id_fields = ("email", "phone",) # Form Class for Student course change class ChangeCourseForm(AdminActionForm): course = forms.ModelChoiceField(queryset=Course.objects.all()) class StudentAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin): - list_display = ("surname", "name", "course", "course_color", "email", "phone", "password", "active") - list_filter = ("course", "active") - actions = ("change_course", "disable_students") + list_display = ("surname", "name", "course", "course_color", "email", "phone", "username", "password", "active",) + list_filter = ("course", "active",) + search_fields= ("surname", "name", "phone", "email",) + actions = ("change_course", "disable_students",) resource_classes = [StudentResource] + confirm_form_class = StudentCustomConfirmImportForm + tmp_storage_class = CacheStorage + skip_admin_log = True @admin.display(description="Color") def course_color(self, obj: Student) -> SafeText: @@ -58,6 +76,10 @@ class StudentAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin): def password(self, obj: Student) -> SafeText: return SafeText(obj.default_password()) + @admin.display(description="Username") + def username(self, obj: Student) -> SafeText: + return SafeText(obj.default_username()) + @admin.action(description="Deactivate Students") def disable_students(self, request: HttpRequest, queryset: QuerySet[Student]): for q in queryset.all(): @@ -73,3 +95,18 @@ class StudentAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin): course = data["course"] count: int = queryset.update(course=course) messages.success(request, f"{count} students updated to {course}") + + # Return the initial form for import confirmations, request course to user + def get_confirm_form_initial(self, request: HttpRequest, import_form): + initial = super().get_confirm_form_initial(request, import_form) + if import_form and hasattr(import_form.cleaned_data, "course"): + course: Course = import_form.cleaned_data["course"] + initial["course"] = course.id + return initial + + # Add course to import form kwargs to be used by resource to associate course with all imported students + def get_import_data_kwargs(self, request: HttpRequest, *args, **kwargs): + form: ImportForm | None = kwargs.get("form", None) + if form and hasattr(form, "cleaned_data"): + kwargs["course"] = form.cleaned_data.get("course", None) + return kwargs diff --git a/cntmanage/flightslot/admins/weekpred_adm.py b/cntmanage/flightslot/admins/weekpref_adm.py similarity index 100% rename from cntmanage/flightslot/admins/weekpred_adm.py rename to cntmanage/flightslot/admins/weekpref_adm.py diff --git a/cntmanage/flightslot/models/students.py b/cntmanage/flightslot/models/students.py index 2582a01..e913747 100644 --- a/cntmanage/flightslot/models/students.py +++ b/cntmanage/flightslot/models/students.py @@ -48,6 +48,12 @@ class Student(models.Model): def default_password(self) -> str: return f"{self.name.lower()[0]}{self.surname.lower()}{self.id}" + + def default_username(self) -> str: + if self.pk and self.user: + return self.user.username + else: + return "" # Override save method to add user for login upon Student creation def save(self, *args, **kwargs):