From 9cae53a942f927cf5435d4522bc75df9c79693b7 Mon Sep 17 00:00:00 2001 From: Emanuele Date: Tue, 18 Nov 2025 23:24:38 +0100 Subject: [PATCH] Import mission profiles and better format text fields --- techdb/flightslot/admins/hourbuilding_adm.py | 11 ++++++ techdb/flightslot/admins/mission_adm.py | 38 ++++++++++++++++++- techdb/flightslot/admins/student_adm.py | 10 ++--- techdb/flightslot/admins/training_adm.py | 7 ++++ ...profile_mtype_alter_weekpreference_week.py | 23 +++++++++++ techdb/flightslot/models/missions.py | 1 + 6 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 techdb/flightslot/migrations/0017_alter_missionprofile_mtype_alter_weekpreference_week.py diff --git a/techdb/flightslot/admins/hourbuilding_adm.py b/techdb/flightslot/admins/hourbuilding_adm.py index d41e7e7..9e7fc06 100644 --- a/techdb/flightslot/admins/hourbuilding_adm.py +++ b/techdb/flightslot/admins/hourbuilding_adm.py @@ -1,6 +1,8 @@ import nested_admin from django import forms +from django.db import models +from django.forms import TextInput, Textarea from django.http import HttpRequest from durationwidget.widgets import TimeDurationWidget @@ -27,6 +29,10 @@ class HourBuildingLegInline(nested_admin.NestedTabularInline): extra = 0 fk_name = 'hb' max_num = 5 + formfield_overrides = { + models.CharField: {'widget': TextInput(attrs={'size':'20'})}, + models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':35})}, + } # If user is a student deny edit permission for week past the current one def has_change_permission(self, request: HttpRequest, obj: HourBuilding | None = None): @@ -46,6 +52,11 @@ class HourBuildingInLine(nested_admin.NestedTabularInline): fk_name = 'weekpref' verbose_name_plural = "Hour Building" max_num = 7 + formfield_overrides = { + models.CharField: {'widget': TextInput(attrs={'size':'20'})}, + models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':35})}, + } + # If user is a student deny edit permission for week past the current one def has_change_permission(self, request: HttpRequest, obj: WeekPreference | None = None): diff --git a/techdb/flightslot/admins/mission_adm.py b/techdb/flightslot/admins/mission_adm.py index fa85fc1..52e2b3e 100644 --- a/techdb/flightslot/admins/mission_adm.py +++ b/techdb/flightslot/admins/mission_adm.py @@ -1,5 +1,39 @@ from django.contrib import admin +from django.utils.safestring import SafeText -class MissionProfileAdmin(admin.ModelAdmin): - list_display = ("mtype", "mnum",) +from typing import Any + +from import_export import fields +from import_export.admin import ImportMixin +from import_export.resources import ModelResource + +from ..models.missions import MissionProfile + +from django_admin_action_forms import AdminActionFormsMixin + +from datetime import timedelta + +# Resource Class for Student data import +class MissionProfileResource(ModelResource): + mtype = fields.Field(attribute="mtype", column_name="mtype") + mnum = fields.Field(attribute="mnum", column_name="mnum") + duration = fields.Field(attribute="duration", column_name="duration") + +# Cleanup fields before entering + def before_import_row(self, row: dict[str, str | Any], **kwargs) -> None: + row["mtype"] = SafeText(row["mtype"].upper().strip()) + row["mnum"] = SafeText(row["mnum"].upper().strip()) + h, m, _ = row["duration"].split(":") + row["duration"] = timedelta(hours=float(h), minutes=float(m)) + return super().before_import_row(row, **kwargs) + + class Meta: + model = MissionProfile + skip_unchanged = True + report_skipped = True + fields = ("mtype", "mnum", "duration") + import_id_fields = ("mtype", "mnum") + +class MissionProfileAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin): + list_display = ("mtype", "mnum", "notes") list_filter = ("mtype",) diff --git a/techdb/flightslot/admins/student_adm.py b/techdb/flightslot/admins/student_adm.py index 15db717..f3adf2d 100644 --- a/techdb/flightslot/admins/student_adm.py +++ b/techdb/flightslot/admins/student_adm.py @@ -18,10 +18,10 @@ from ..custom.colortag import course_color # Resource Class for Student data import class StudentResource(ModelResource): - surname = fields.Field(attribute="surname", column_name="surname", widget=CharWidget()) - name = fields.Field(attribute="name", column_name="name", widget=CharWidget()) - email = fields.Field(attribute="email", column_name="email", widget=CharWidget()) - phone = fields.Field(attribute="phone", column_name="phone", widget=CharWidget()) + surname = fields.Field(attribute="surname", column_name="surname") + name = fields.Field(attribute="name", column_name="name") + email = fields.Field(attribute="email", column_name="email") + phone = fields.Field(attribute="phone", column_name="phone") # Cleanup fields before entering def before_import_row(self, row: dict[str, str], **kwargs) -> None: @@ -42,7 +42,7 @@ class StudentResource(ModelResource): class ChangeCourseForm(AdminActionForm): course = forms.ModelChoiceField(queryset=Course.objects.all()) -class StudentAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin): +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") diff --git a/techdb/flightslot/admins/training_adm.py b/techdb/flightslot/admins/training_adm.py index 04a3b54..248d5b9 100644 --- a/techdb/flightslot/admins/training_adm.py +++ b/techdb/flightslot/admins/training_adm.py @@ -1,5 +1,7 @@ import nested_admin from django import forms +from django.db import models +from django.forms import TextInput, Textarea from django.http import HttpRequest from ..models.missions import Training @@ -18,6 +20,11 @@ class TrainingInLIne(nested_admin.NestedTabularInline): verbose_name_plural = "Training Missions" max_num = 7 + formfield_overrides = { + models.CharField: {'widget': TextInput(attrs={'size':'20'})}, + models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':35})}, + } + # If user is a student deny edit permission for week past the current one def has_change_permission(self, request: HttpRequest, obj: WeekPreference | None = None): if hasattr(request.user, 'student') and obj: diff --git a/techdb/flightslot/migrations/0017_alter_missionprofile_mtype_alter_weekpreference_week.py b/techdb/flightslot/migrations/0017_alter_missionprofile_mtype_alter_weekpreference_week.py new file mode 100644 index 0000000..a60528c --- /dev/null +++ b/techdb/flightslot/migrations/0017_alter_missionprofile_mtype_alter_weekpreference_week.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.8 on 2025-11-18 21:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('flightslot', '0016_alter_course_cnumber_alter_course_color_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='missionprofile', + name='mtype', + field=models.CharField(choices=[('OTHER', 'OTHER'), ('PPL', 'PPL'), ('IR', 'IR'), ('MEP', 'MEP'), ('CPL', 'CPL'), ('FI', 'FI'), ('PC', 'PC'), ('CHK', 'CHK_6M')], default='PPL', verbose_name='Mission Type'), + ), + migrations.AlterField( + model_name='weekpreference', + name='week', + field=models.PositiveSmallIntegerField(auto_created=True, db_default=47, db_index=True, verbose_name='Week Number'), + ), + ] diff --git a/techdb/flightslot/models/missions.py b/techdb/flightslot/models/missions.py index 4c79b07..2be822d 100644 --- a/techdb/flightslot/models/missions.py +++ b/techdb/flightslot/models/missions.py @@ -8,6 +8,7 @@ class MissionType(models.TextChoices): OTHER = "OTHER", _("OTHER") PPL = "PPL", _("PPL") IR = "IR", _("IR") + MEP = "MEP", _("MEP") CPL = "CPL", _("CPL") FI = "FI", _("FI") PC = "PC", _("PC")