Compare commits
2 Commits
edb54e9f6f
...
9cae53a942
| Author | SHA1 | Date | |
|---|---|---|---|
| 9cae53a942 | |||
| 79d7333ca0 |
@@ -1,282 +1,14 @@
|
|||||||
from django import forms
|
from django.contrib import admin
|
||||||
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.courses import Course
|
||||||
from .models.hourbuildings import HourBuilding, HourBuildingLeg
|
|
||||||
from .models.missions import Training, MissionProfile
|
|
||||||
from .models.students import Student
|
from .models.students import Student
|
||||||
|
from .models.missions import MissionProfile
|
||||||
from .models.weekpref import WeekPreference
|
from .models.weekpref import WeekPreference
|
||||||
|
|
||||||
from .custom.colortag import course_color
|
from .admins.course_adm import CourseAdmin
|
||||||
from .actions.exportweek import export_selected
|
from .admins.student_adm import StudentAdmin
|
||||||
|
from .admins.mission_adm import MissionProfileAdmin
|
||||||
from datetime import date
|
from .admins.weekpred_adm import WeekPreferenceAdmin
|
||||||
|
|
||||||
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(Course, CourseAdmin)
|
||||||
admin.site.register(MissionProfile, MissionProfileAdmin)
|
admin.site.register(MissionProfile, MissionProfileAdmin)
|
||||||
|
|||||||
16
techdb/flightslot/admins/course_adm.py
Normal file
16
techdb/flightslot/admins/course_adm.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from django.utils.safestring import SafeText
|
||||||
|
|
||||||
|
from ..models.courses import Course
|
||||||
|
from ..custom.colortag import course_color
|
||||||
|
|
||||||
|
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)
|
||||||
70
techdb/flightslot/admins/hourbuilding_adm.py
Normal file
70
techdb/flightslot/admins/hourbuilding_adm.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
from ..models.hourbuildings import HourBuilding, HourBuildingLeg
|
||||||
|
from ..models.weekpref import WeekPreference
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
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
|
||||||
|
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):
|
||||||
|
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
|
||||||
|
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:
|
||||||
|
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)
|
||||||
39
techdb/flightslot/admins/mission_adm.py
Normal file
39
techdb/flightslot/admins/mission_adm.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from django.utils.safestring import SafeText
|
||||||
|
|
||||||
|
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",)
|
||||||
75
techdb/flightslot/admins/student_adm.py
Normal file
75
techdb/flightslot/admins/student_adm.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
from django import forms
|
||||||
|
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.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.students import Student
|
||||||
|
|
||||||
|
from ..custom.colortag import course_color
|
||||||
|
|
||||||
|
# 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(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}")
|
||||||
37
techdb/flightslot/admins/training_adm.py
Normal file
37
techdb/flightslot/admins/training_adm.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
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
|
||||||
|
from ..models.weekpref import WeekPreference
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
class TrainingForm(forms.ModelForm):
|
||||||
|
model=Training
|
||||||
|
|
||||||
|
class TrainingInLIne(nested_admin.NestedTabularInline):
|
||||||
|
model = Training
|
||||||
|
form = TrainingForm
|
||||||
|
extra = 0
|
||||||
|
fk_name = 'weekpref'
|
||||||
|
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:
|
||||||
|
current_week: int = 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)
|
||||||
126
techdb/flightslot/admins/weekpred_adm.py
Normal file
126
techdb/flightslot/admins/weekpred_adm.py
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
import nested_admin
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
from ..models.missions import Training
|
||||||
|
from ..models.weekpref import WeekPreference
|
||||||
|
|
||||||
|
from .training_adm import TrainingInLIne
|
||||||
|
from .hourbuilding_adm import HourBuildingInLine
|
||||||
|
|
||||||
|
from ..custom.colortag import course_color
|
||||||
|
from ..actions.exportweek import export_selected
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
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(self, request: HttpRequest, queryset: QuerySet[WeekPreference]) -> HttpResponse | None:
|
||||||
|
if queryset.count() == 0:
|
||||||
|
return None
|
||||||
|
self.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)
|
||||||
@@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -8,6 +8,7 @@ class MissionType(models.TextChoices):
|
|||||||
OTHER = "OTHER", _("OTHER")
|
OTHER = "OTHER", _("OTHER")
|
||||||
PPL = "PPL", _("PPL")
|
PPL = "PPL", _("PPL")
|
||||||
IR = "IR", _("IR")
|
IR = "IR", _("IR")
|
||||||
|
MEP = "MEP", _("MEP")
|
||||||
CPL = "CPL", _("CPL")
|
CPL = "CPL", _("CPL")
|
||||||
FI = "FI", _("FI")
|
FI = "FI", _("FI")
|
||||||
PC = "PC", _("PC")
|
PC = "PC", _("PC")
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ INSTALLED_APPS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Import Export plugin settings
|
# Import Export plugin settings
|
||||||
|
from import_export.formats.base_formats import CSV
|
||||||
IMPORT_EXPORT_USE_TRANSACTIONS = True
|
IMPORT_EXPORT_USE_TRANSACTIONS = True
|
||||||
IMPORT_EXPORT_SKIP_ADMIN_LOG = True
|
IMPORT_EXPORT_SKIP_ADMIN_LOG = True
|
||||||
from import_export.formats.base_formats import CSV, XLSX
|
IMPORT_FORMATS = [CSV]
|
||||||
IMPORT_FORMATS = [CSV, XLSX]
|
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
|||||||
Reference in New Issue
Block a user