Files
catops/techdb/flightslot/admin.py

285 lines
12 KiB
Python

from django import forms
from django.db.models.query import QuerySet
from django.http import HttpRequest, HttpResponse
from django.contrib import admin, messages
from django.utils.translation import ngettext
from django.utils.safestring import SafeText
import nested_admin
from durationwidget.widgets import TimeDurationWidget
from import_export import fields
from import_export.admin import ImportMixin
from import_export.resources import ModelResource
from import_export.widgets import CharWidget
from django_admin_action_forms import AdminActionFormsMixin, AdminActionForm, action_with_form
from .models.courses import Course
from .models.hourbuildings import HourBuilding, HourBuildingLeg
from .models.missions import Training, MissionProfile
from .models.students import Student
from .models.weekpref import WeekPreference
from .custom.colortag import course_color
from .actions.exportweek import export_selected
from datetime import date
class TrainingForm(forms.ModelForm):
model=Training
class HourBuildingLegForm(forms.ModelForm):
class Meta:
model = HourBuildingLeg
fields = '__all__'
widgets = {
'time': TimeDurationWidget(show_days=False,
show_seconds=False
)
}
# Register your models here.
class HourBuildingLegInline(nested_admin.NestedTabularInline):
model = HourBuildingLeg
form = HourBuildingLegForm
extra = 0
fk_name = 'hb'
max_num = 5
# 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):
if hasattr(request.user, 'student') and obj:
current_week = date.today().isocalendar().week
if not obj.DoesNotExist and current_week > obj.weekpref.week:
return False
return True
def has_delete_permission(self, request: HttpRequest, obj: HourBuilding | None = None):
return self.has_change_permission(request=request, obj=obj)
class HourBuildingInLine(nested_admin.NestedTabularInline):
model = HourBuilding
extra = 0
inlines = [HourBuildingLegInline]
fk_name = 'weekpref'
verbose_name_plural = "Hour Building"
max_num = 7
# 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:
current_week = date.today().isocalendar().week
if current_week > obj.week:
return False
return True
def has_delete_permission(self, request: HttpRequest, obj: WeekPreference | None = None):
return self.has_change_permission(request=request, obj=obj)
class TrainingInLIne(nested_admin.NestedTabularInline):
model = Training
form = TrainingForm
extra = 0
fk_name = 'weekpref'
verbose_name_plural = "Training Missions"
max_num = 7
# 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:
current_week = date.today().isocalendar().week
if current_week > obj.week:
return False
return True
def has_delete_permission(self, request: HttpRequest, obj: WeekPreference | None = None):
return self.has_change_permission(request=request, obj=obj)
class WeekPreferenceAdmin(nested_admin.NestedModelAdmin):
inlines = (TrainingInLIne, HourBuildingInLine,)
list_display = ("week", "student__surname","student__name", "student__course", "course_color", "student_brief_mix",)
list_filter = ("week", "student__course", "student",)
actions = ("export",)
@admin.action(description="Export Selected Preferences")
def export(weekpreferenceadmin, request: HttpRequest, queryset: QuerySet[WeekPreference]) -> HttpResponse | None:
if queryset.count() == 0:
return None
weekpreferenceadmin.message_user(request, ngettext("Exporting %d row", "Exporting %d rows", queryset.count()) % queryset.count(), messages.SUCCESS)
return export_selected(request=request, queryset=queryset)
@admin.display(description="Mission Count")
def student_brief_mix(self, obj: WeekPreference) -> SafeText:
if not obj.student.course:
return SafeText("")
return SafeText(f"{Training.objects.filter(weekpref = obj.id).count()}")
@admin.display(description="Color")
def course_color(self, obj: WeekPreference) -> SafeText:
if not obj.student.course:
return SafeText("")
return course_color(obj.student.course.color)
# If a user is registered as student hide filters
def get_list_filter(self, request):
list_filter = super().get_list_filter(request)
if hasattr(request.user, 'student'):
return []
return list_filter
# If a user is registered as student do not show actions
def get_actions(self, request):
actions = super().get_actions(request)
if hasattr(request.user, 'student'):
return []
return actions
# If a user is registered as student show only their preferences
def get_queryset(self, request):
qs = super().get_queryset(request)
if hasattr(request.user, 'student'):
return qs.filter(student=request.user.student)
# If admin show everything
return qs
def get_form(self, request, obj=None, **kwargs):
form: forms.Form = super().get_form(request, obj, **kwargs)
current_week = date.today().isocalendar().week
# If form contains the week field
if 'week' in form.base_fields:
# Set default value as current week
form.base_fields['week'].initial = current_week
# If student is current user making request
if hasattr(request.user, 'student'):
student = request.user.student
if 'student' in form.base_fields:
form.base_fields['student'].initial = student
form.base_fields['student'].disabled = True
form.base_fields['week'].disabled = True # student cannot change week
return form
# If user is a student deny edit permission for week past the current one
def has_change_permission(self, request, obj: WeekPreference | None = None):
if hasattr(request.user, 'student') and obj:
current_week = date.today().isocalendar().week
if current_week > obj.week:
return False
return True
# If user is a student deny edit permission for week past the current one
def has_add_permission(self, request, obj: WeekPreference | None = None):
if hasattr(request.user, 'student') and obj:
current_week = date.today().isocalendar().week
if current_week > obj.week:
return False
return True
# If user is a student deny edit permission for week past the current one
def has_delete_permission(self, request, obj: WeekPreference | None = None):
if hasattr(request.user, 'student') and obj:
current_week = date.today().isocalendar().week
if current_week > obj.week:
return False
return True
def changeform_view(self, request: HttpRequest, object_id: int | None = None, form_url: str = '', extra_context=None):
extra_context = extra_context or {}
if hasattr(request.user, 'student') and object_id:
current_week = date.today().isocalendar().week
weekpref = WeekPreference.objects.get(id=object_id)
if current_week > weekpref.week:
extra_context['show_save'] = False
extra_context['show_save_and_continue'] = False
extra_context['show_save_and_add_another'] = False
extra_context['show_delete'] = False
return super().changeform_view(request, object_id, form_url, extra_context)
def save_model(self, request, obj, form, change):
# Imposta automaticamente lo studente se non è già valorizzato
if hasattr(request.user, 'student') and not obj.student_id:
obj.student = request.user.student
super().save_model(request, obj, form, change)
# 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())
# 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())
row['phone'] = SafeText(row['phone'].replace(' ',''))
row['email'] = SafeText(row['email'].lower().strip())
return super().before_import_row(row, **kwargs)
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 = 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")
resource_classes = [StudentResource]
@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.action(description="Disable Students")
def disable_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")
pass
@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}")
class CourseAdmin(admin.ModelAdmin):
list_display = ("ctype", "cnumber","color_display", "year")
list_filter = ("ctype", "year")
# Dinamically add color_display property to show a colored dot
@admin.display(description="Color")
def color_display(self, obj: Course) -> SafeText:
if not obj.pk:
return SafeText("")
return course_color(obj.color)
class MissionProfileAdmin(admin.ModelAdmin):
list_display = ("mtype", "mnum",)
list_filter = ("mtype",)
admin.site.register(Course, CourseAdmin)
admin.site.register(MissionProfile, MissionProfileAdmin)
admin.site.register(Student, StudentAdmin)
admin.site.register(WeekPreference, WeekPreferenceAdmin)