137 lines
6.0 KiB
Python
137 lines
6.0 KiB
Python
from django.forms import ModelChoiceField, TypedMultipleChoiceField
|
|
from django.db.models.query import QuerySet
|
|
from django.http import HttpRequest
|
|
from django.contrib import admin, messages
|
|
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.forms import ConfirmImportForm, ImportForm
|
|
|
|
from django_admin_action_forms import AdminActionFormsMixin, AdminActionForm, ActionForm, action_with_form
|
|
from admin_confirm import AdminConfirmMixin, confirm_action
|
|
|
|
from ..models.aircrafts import AircraftTypes
|
|
from ..models.courses import Course
|
|
from ..models.students import Student
|
|
|
|
from ..actions.assign_aircraft import assign_aircraft
|
|
from ..actions.send_email import send_mail_password
|
|
|
|
from ..custom.colortag import course_color
|
|
|
|
from typing import Any, Dict, List
|
|
|
|
# Custom import form to select a course for student input
|
|
class StudentCustomConfirmImportForm(ConfirmImportForm):
|
|
course = ModelChoiceField(
|
|
queryset=Course.objects.all(),
|
|
required=False)
|
|
|
|
# Resource Class for Student data import
|
|
class StudentResource(ModelResource):
|
|
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:
|
|
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 | Course]):
|
|
course = kwargs.get("course", None)
|
|
if course and isinstance(course, Course):
|
|
instance.course = course
|
|
|
|
class Meta:
|
|
model = Student
|
|
skip_unchanged = True
|
|
report_skipped = True
|
|
fields = ("surname", "name", "email", "phone",)
|
|
import_id_fields = ("email", "phone",)
|
|
|
|
# Form Class for Student course change
|
|
class ChangeCourseForm(AdminActionForm):
|
|
course = ModelChoiceField(queryset=Course.objects.all().order_by("ctype", "-cnumber"))
|
|
|
|
# Form class to assing aircrafts to students
|
|
class ChangeAircraftForm(AdminActionForm):
|
|
aircrafts = TypedMultipleChoiceField(choices=AircraftTypes)
|
|
|
|
|
|
class StudentAdmin(ImportMixin, AdminConfirmMixin, AdminActionFormsMixin, admin.ModelAdmin):
|
|
model = Student
|
|
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", "deactivate_students", "change_aircraft", "send_mail", )
|
|
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:
|
|
if not obj.course:
|
|
return SafeText("")
|
|
return course_color(obj.course.color)
|
|
|
|
@admin.display(description="Password")
|
|
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 deactivate_students(self, request: HttpRequest, queryset: QuerySet[Student]):
|
|
for q in queryset.all():
|
|
if q.user:
|
|
q.user.is_staff = False
|
|
q.user.save()
|
|
count: int = queryset.update(active = False)
|
|
messages.success(request, f"{count} students deactivated")
|
|
|
|
@action_with_form(ChangeCourseForm, description="Change Student Course")
|
|
def change_course(self, request: HttpRequest, queryset: QuerySet[Student], data):
|
|
course = data["course"]
|
|
count: int = queryset.update(course=course)
|
|
messages.success(request, f"{count} students updated to {course}")
|
|
|
|
@action_with_form(ChangeAircraftForm, description="Assign Aircraft Type")
|
|
def change_aircraft(self, request: HttpRequest, queryset: QuerySet[Student], data: Dict[str, List[AircraftTypes]]):
|
|
i: int
|
|
ac_types: List[str]
|
|
i, ac_types = assign_aircraft(queryset=queryset, data=data)
|
|
messages.success(request, f"{i} Students updated to {ac_types}")
|
|
|
|
@confirm_action
|
|
@admin.action(description="Send Access Credentials e-mail")
|
|
def send_mail(self, request: HttpRequest, queryset: QuerySet[Student], *args: Any) -> None:
|
|
send_mail_password(request=request, queryset=queryset)
|
|
|
|
# Return the initial form for import confirmations, request course to user
|
|
def get_confirm_form_initial(self, request: HttpRequest, import_form) -> Dict[str, Any]:
|
|
initial: Dict[str, Any] = 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) -> Dict[str, Any]:
|
|
form: ImportForm | None = kwargs.get("form", None)
|
|
if form and hasattr(form, "cleaned_data"):
|
|
kwargs["course"] = form.cleaned_data.get("course", None)
|
|
return kwargs
|