Added instructor availability model and admin
This commit is contained in:
@@ -2,10 +2,12 @@ from django.contrib import admin
|
||||
from django.urls import path
|
||||
from django.shortcuts import redirect
|
||||
from flightslot.admin import flightslot_user
|
||||
from flightslot.admin import flightslot_staff
|
||||
|
||||
urlpatterns = [
|
||||
#path('', RedirectView.as_view(url='/admin/', permanent=False)),
|
||||
path('admin/', admin.site.urls),
|
||||
path('user/', flightslot_user.urls),
|
||||
path('staff/', flightslot_staff.urls),
|
||||
path("", lambda r: redirect("/user/")), # la root porta gli utenti nella pagina giusta
|
||||
]
|
||||
|
||||
@@ -6,7 +6,8 @@ from .models.courses import Course
|
||||
from .models.students import Student
|
||||
from .models.missions import MissionProfile
|
||||
from .models.weekpref import WeekPreference
|
||||
from.models.instructors import Instructor
|
||||
from .models.instructors import Instructor
|
||||
from .models.availabilities import Availability
|
||||
|
||||
from .admins.aircraft_adm import AircraftAdmin
|
||||
from .admins.course_adm import CourseAdmin
|
||||
@@ -14,16 +15,19 @@ from .admins.student_adm import StudentAdmin
|
||||
from .admins.mission_adm import MissionProfileAdmin
|
||||
from .admins.weekpref_adm import WeekPreferenceAdmin
|
||||
from .admins.instructor_admin import InstructorAdmin
|
||||
from .admins.availability_adm import AvailabilityAdmin
|
||||
|
||||
from django.contrib.admin import AdminSite
|
||||
|
||||
from os import environ
|
||||
|
||||
# User website under /user/ URL
|
||||
##################################
|
||||
# User website under /user/ URL #
|
||||
##################################
|
||||
class FlightSlotUserSite(AdminSite):
|
||||
site_header = "Flight Scheduler 🛫"
|
||||
site_title = "Flight Scheduler 🛫"
|
||||
index_title = "Welcome to CantorAir Flight Scheduler Portal"
|
||||
index_title = "Welcome to CantorAir Flight Scheduler Student Portal"
|
||||
|
||||
def get_app_list(self, request: HttpRequest, *args, **kwargs):
|
||||
app_list = super().get_app_list(request)
|
||||
@@ -37,6 +41,26 @@ class FlightSlotUserSite(AdminSite):
|
||||
flightslot_user = FlightSlotUserSite(name="user_site")
|
||||
flightslot_user.register(WeekPreference, WeekPreferenceAdmin)
|
||||
|
||||
##################################
|
||||
# User website under /staff/ URL #
|
||||
##################################
|
||||
class FlightSlotStaffSite(AdminSite):
|
||||
site_header = "Flight Scheduler Staff 🛫"
|
||||
site_title = "Flight Scheduler Staff 🛫"
|
||||
index_title = "Welcome to CantorAir Flight Scheduler Staff Portal"
|
||||
|
||||
def get_app_list(self, request: HttpRequest, *args, **kwargs):
|
||||
app_list = super().get_app_list(request)
|
||||
|
||||
if not request.user.is_superuser:
|
||||
self.enable_nav_sidebar = False
|
||||
|
||||
return app_list
|
||||
|
||||
# Register only user visible models
|
||||
flightslot_staff = FlightSlotUserSite(name="staff_site")
|
||||
flightslot_staff.register(Availability, AvailabilityAdmin)
|
||||
|
||||
|
||||
# Get version for debug purposes
|
||||
ver: str = environ.get("VERSION", "dev")
|
||||
@@ -51,3 +75,4 @@ admin.site.register(MissionProfile, MissionProfileAdmin)
|
||||
admin.site.register(Student, StudentAdmin)
|
||||
admin.site.register(WeekPreference, WeekPreferenceAdmin)
|
||||
admin.site.register(Instructor, InstructorAdmin)
|
||||
admin.site.register(Availability, AvailabilityAdmin)
|
||||
|
||||
66
cntmanage/flightslot/admins/availability_adm.py
Normal file
66
cntmanage/flightslot/admins/availability_adm.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from django import forms
|
||||
from django.db.models.query import QuerySet
|
||||
from django.http import HttpRequest
|
||||
from django.contrib import admin
|
||||
from django.utils.safestring import SafeText
|
||||
|
||||
from ..models.instructors import Instructor
|
||||
from ..models.availabilities import Availability
|
||||
|
||||
from datetime import date
|
||||
from typing import Any, List
|
||||
|
||||
class AvailabilityForm(forms.ModelForm):
|
||||
model=Availability
|
||||
|
||||
class AvailabilityAdmin(admin.ModelAdmin):
|
||||
model = Availability
|
||||
list_display = ("week", "instructor__surname", "instructor__name", "days_available", "hours")
|
||||
list_filter = ("week", )
|
||||
search_fields = ("instructor__surname","instructor__name", )
|
||||
#actions = ("export", )
|
||||
|
||||
@admin.display(description="Days Available")
|
||||
def days_available(self, obj: Availability) -> SafeText:
|
||||
if not obj:
|
||||
return SafeText("")
|
||||
days: List[str | None] = [
|
||||
"Mon" if obj.monday else None,
|
||||
"Tue" if obj.tuesday else None,
|
||||
"Wed" if obj.wednesday else None,
|
||||
"Thu" if obj.thursday else None,
|
||||
"Fri" if obj.friday else None,
|
||||
"Sat" if obj.saturday else None,
|
||||
"Sun" if obj.sunday else None,
|
||||
]
|
||||
return SafeText("/".join(d if d else "" for d in days))
|
||||
|
||||
def get_queryset(self, request: HttpRequest) -> QuerySet:
|
||||
return super().get_queryset(request).order_by("-week", "instructor__surname", "instructor__name")
|
||||
|
||||
def get_form(self, request: HttpRequest, obj: Availability | None = None, change: bool = False, **kwargs: Any) -> AvailabilityForm:
|
||||
form: AvailabilityForm = super().get_form(request, obj, change, **kwargs)
|
||||
|
||||
if change: # if is only a form change do not set default values and return form
|
||||
return form
|
||||
|
||||
# If form contains the week field
|
||||
current_week = date.today().isocalendar().week
|
||||
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, "instructor"):
|
||||
instructor: Instructor = request.user.instructor
|
||||
if "instructor" in form.base_fields:
|
||||
form.base_fields["instructor"].initial = instructor
|
||||
form.base_fields["instructor"].disabled = True
|
||||
return form
|
||||
|
||||
# Imposta automaticamente l'istruttore se non è già valorizzato
|
||||
def save_model(self, request: HttpRequest, obj: Availability, form: AvailabilityForm, change: bool):
|
||||
if hasattr(request.user, "instructor") and not obj.instructor_id:
|
||||
obj.instructor = request.user.instructor
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
@@ -93,13 +93,13 @@ class WeekPreferenceAdmin(nested_admin.NestedPolymorphicModelAdmin):
|
||||
|
||||
# If user is a student deny edit permission for week past the current one
|
||||
def has_add_permission(self, request: HttpRequest, obj: WeekPreference | None = None) -> bool:
|
||||
return self.has_change_permission(request, obj)
|
||||
return not obj and self.has_change_permission(request, obj)
|
||||
|
||||
# If user is a student deny edit permission for week past the current one
|
||||
def has_delete_permission(self, request: HttpRequest, obj: WeekPreference | None = None)-> bool:
|
||||
return self.has_change_permission(request, obj)
|
||||
|
||||
def changeform_view(self, request: HttpRequest, object_id: int | None = None, form_url: str = "", extra_context=None):
|
||||
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:
|
||||
weekpref = WeekPreference.objects.get(id=object_id)
|
||||
|
||||
@@ -12,6 +12,6 @@ def has_edit_permission(request: HttpRequest, obj: WeekPreference | None = None)
|
||||
if not student.active:
|
||||
return False
|
||||
current_week: int = date.today().isocalendar().week
|
||||
if obj and current_week > obj.week or not student.active:
|
||||
if obj and (current_week > obj.week or not student.active):
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -7,8 +7,10 @@ class RedirectNonSuperuserFromAdminMiddleware:
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request: HttpRequest):
|
||||
# Se l'utente è loggato, non è superuser e prova ad andare in /admin/...
|
||||
# Se l'utente è loggato, non è superuser e prova ad andare in /admin/... o qualsiasi altro path
|
||||
if hasattr(request, "user") and not request.user.is_superuser:
|
||||
if "/admin/" in request.path:
|
||||
if hasattr(request.user, "student") and not "/user/" in request.path:
|
||||
return redirect("/user/") # redirect automatico
|
||||
elif hasattr(request.user, "instructor") and not "/staff/" in request.path:
|
||||
return redirect("/staff/") # redirect automatico
|
||||
return self.get_response(request)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Generated by Django 5.2.8 on 2025-12-02 10:02
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('flightslot', '0026_alter_student_email_alter_student_phone_instructor'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='weekpreference',
|
||||
name='student',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='flightslot.student', verbose_name='Student Selection'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Availability',
|
||||
fields=[
|
||||
('week', models.PositiveSmallIntegerField(auto_created=True, db_default=49, db_index=True, verbose_name='Week Number')),
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('monday', models.BooleanField(default=True)),
|
||||
('tuesday', models.BooleanField(default=True)),
|
||||
('wednesday', models.BooleanField(default=True)),
|
||||
('thursday', models.BooleanField(default=True)),
|
||||
('friday', models.BooleanField(default=True)),
|
||||
('saturday', models.BooleanField(default=True)),
|
||||
('sunday', models.BooleanField(default=True)),
|
||||
('hours', models.DurationField(null=True, verbose_name='Available hours')),
|
||||
('notes', models.TextField(blank=True, max_length=140, null=True)),
|
||||
('instructor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='flightslot.instructor', verbose_name='Instructor Selection')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 5.2.8 on 2025-12-02 10:59
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('flightslot', '0027_alter_weekpreference_student_availability'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='availability',
|
||||
options={'verbose_name': 'Instructor Availability', 'verbose_name_plural': 'Instructor Availabilities'},
|
||||
),
|
||||
]
|
||||
79
cntmanage/flightslot/models/availabilities.py
Normal file
79
cntmanage/flightslot/models/availabilities.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from django.db import models
|
||||
from datetime import date
|
||||
|
||||
from ..models.instructors import Instructor
|
||||
|
||||
class Availability(models.Model):
|
||||
id = models.BigAutoField(
|
||||
primary_key=True
|
||||
)
|
||||
|
||||
week = models.PositiveSmallIntegerField(
|
||||
null=False,
|
||||
db_index=True,
|
||||
db_default=date.today().isocalendar().week,
|
||||
auto_created=True,
|
||||
verbose_name="Week Number"
|
||||
)
|
||||
|
||||
instructor = models.ForeignKey(
|
||||
Instructor,
|
||||
null=False,
|
||||
db_index=True,
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="Instructor Selection"
|
||||
)
|
||||
|
||||
monday = models.BooleanField(
|
||||
default=True,
|
||||
null=False
|
||||
)
|
||||
|
||||
tuesday = models.BooleanField(
|
||||
default=True,
|
||||
null=False
|
||||
)
|
||||
|
||||
wednesday = models.BooleanField(
|
||||
default=True,
|
||||
null=False
|
||||
)
|
||||
|
||||
thursday = models.BooleanField(
|
||||
default=True,
|
||||
null=False
|
||||
)
|
||||
|
||||
friday = models.BooleanField(
|
||||
default=True,
|
||||
null=False
|
||||
)
|
||||
|
||||
saturday = models.BooleanField(
|
||||
default=True,
|
||||
null=False
|
||||
)
|
||||
|
||||
sunday = models.BooleanField(
|
||||
default=True,
|
||||
null=False
|
||||
)
|
||||
|
||||
hours = models.DurationField(
|
||||
null=True,
|
||||
verbose_name="Available hours"
|
||||
)
|
||||
|
||||
notes = models.TextField(
|
||||
max_length=140,
|
||||
null=True,
|
||||
blank=True
|
||||
)
|
||||
|
||||
class Meta():
|
||||
verbose_name = "Instructor Availability"
|
||||
verbose_name_plural = "Instructor Availabilities"
|
||||
|
||||
def __str__(self):
|
||||
return f"Week {self.week} - {self.instructor.surname} {self.instructor.name[0]}."
|
||||
|
||||
@@ -20,7 +20,7 @@ class WeekPreference(models.Model):
|
||||
Student,
|
||||
null=False,
|
||||
db_index=True,
|
||||
on_delete=models.DO_NOTHING,
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="Student Selection"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user