72 lines
3.0 KiB
Python
72 lines
3.0 KiB
Python
from django.forms import ModelChoiceField, TypedMultipleChoiceField, ModelMultipleChoiceField
|
|
from django.contrib import admin, messages
|
|
from django.http import HttpRequest
|
|
from django.db.models.query import QuerySet, Q
|
|
from django.utils.safestring import SafeText
|
|
|
|
from django_admin_action_forms import AdminActionFormsMixin, AdminActionForm, action_with_form
|
|
|
|
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 ..models.aircrafts import Aircraft
|
|
from ..models.missions import MissionProfile
|
|
|
|
from datetime import timedelta
|
|
from typing import Any, Dict
|
|
|
|
# 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):
|
|
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))
|
|
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",)
|
|
|
|
# Form class to assing aircrafts to students
|
|
class ChangeAircraftForm(AdminActionForm):
|
|
aircrafts = ModelMultipleChoiceField(queryset=Aircraft.objects.distinct('type').all())
|
|
|
|
class MissionProfileAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin):
|
|
list_display = ("mtype", "mnum", "assigned_aircrafts", "duration", "notes", )
|
|
list_filter = ("mtype", )
|
|
actions = ("assign_aircraft", )
|
|
tmp_storage_class = CacheStorage
|
|
skip_admin_log = True
|
|
|
|
@action_with_form(ChangeAircraftForm, description="Assign Aircraft")
|
|
def assign_aircraft(self, request: HttpRequest, queryset: QuerySet[MissionProfile], data: Dict[str, QuerySet[Aircraft]]):
|
|
ac_types = [t.type for t in data["aircrafts"]]
|
|
ac_query: Q = Q() # Build an or query to select all aircrafts of the specified types
|
|
for a in ac_types:
|
|
ac_query |= Q(type=a)
|
|
aircrafts: QuerySet[Aircraft] = Aircraft.objects.filter(ac_query).all() # Execute query
|
|
i: int = 0
|
|
for mix in queryset:
|
|
mix.aircrafts.clear()
|
|
for ac in aircrafts:
|
|
mix.aircrafts.add(ac)
|
|
mix.save()
|
|
i += 1
|
|
messages.success(request, f"{i} Students updated to {ac_types}")
|
|
|
|
@admin.display(description="Assigned Aircrafts")
|
|
def assigned_aircrafts(self, obj: MissionProfile) -> SafeText:
|
|
if not obj.aircrafts:
|
|
return SafeText("")
|
|
return SafeText("/".join(ac.markings for ac in obj.aircrafts.all())) |