Nested polymorphic hour building legs and stops added, needs restyling

This commit is contained in:
2025-11-21 15:25:29 +01:00
parent bcdc885d66
commit 02990d4b2f
9 changed files with 124 additions and 51 deletions

View File

@@ -43,6 +43,7 @@ INSTALLED_APPS = [
'colorfield',
'import_export',
'django_admin_action_forms',
'polymorphic'
]
# Import Export plugin settings
@@ -52,7 +53,7 @@ IMPORT_EXPORT_SKIP_ADMIN_LOG = True
IMPORT_FORMATS = [CSV]
MIDDLEWARE = [
'flightslot.middleware.RedirectNonSuperuserFromAdminMiddleware',
'flightslot.middleware.RedirectNonSuperuserFromAdminMiddleware', # custom middleware to show "user" page to non superuser
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',

View File

@@ -10,7 +10,7 @@ from typing import List
from ..models.weekpref import WeekPreference
from ..models.missions import Training
from ..models.hourbuildings import HourBuilding,HourBuildingLeg
from ..models.hourbuildings import HourBuilding, HourBuildingLegFlight, HourBuildingLegStop
def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> HttpResponse:
@@ -121,9 +121,9 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) ->
hb_name if h.sunday else ""
]
hb_notes = f"{h.notes}\n----\n" if h.notes else ""
hb_legs = HourBuildingLeg.objects.filter(hb_id = h.id)
for hh in hb_legs:
hb_notes += f"{hh.departure} -> {hh.destination} [{hh.time}]\n" if not hh.stop else f"STOP at {hh.departure} [{hh.time}]\n"
hb_legs = HourBuildingLegFlight.objects.filter(hb_id = h.id)
#for hh in hb_legs:
# hb_notes += f"{hh.departure} -> {hh.destination} [{hh.time}]\n" if not hh.stop else f"STOP at {hh.departure} [{hh.time}]\n"
hb_notes.strip('\n')
hb_data.append([str(q.week), *student_data, *hb_days, str(q.student.phone), q.student.email, hb_notes])

View File

@@ -10,6 +10,7 @@ from .admins.course_adm import CourseAdmin
from .admins.student_adm import StudentAdmin
from .admins.mission_adm import MissionProfileAdmin
from .admins.weekpred_adm import WeekPreferenceAdmin
#from .admins.hourbuilding_adm import HourBuilding, HourBuildingInLine
from django.contrib.admin import AdminSite

View File

@@ -7,32 +7,33 @@ from django.http import HttpRequest
from durationwidget.widgets import TimeDurationWidget
from ..models.hourbuildings import HourBuilding, HourBuildingLeg
from ..models.hourbuildings import HourBuilding, HourBuildingLegBase, HourBuildingLegFlight, HourBuildingLegStop
from ..models.weekpref import WeekPreference
from datetime import date
class HourBuildingLegForm(forms.ModelForm):
class Meta:
model = HourBuildingLeg
model = HourBuildingLegFlight
fields = '__all__'
widgets = {
'time': TimeDurationWidget(show_days=False,
show_seconds=False
)
show_seconds=False)
}
# Register your models here.
class HourBuildingLegInline(nested_admin.NestedTabularInline):
model = HourBuildingLeg
form = HourBuildingLegForm
extra = 0
class HourBuildingLegBaseInLine(nested_admin.NestedStackedPolymorphicInline):
model = HourBuildingLegBase
fk_name = 'hb'
max_num = 5
formfield_overrides = {
models.CharField: {'widget': TextInput(attrs={'size':'20'})},
models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':35})},
}
verbose_name_plural = "Hour Building Legs"
class HourBuildingLegFlightInLine(nested_admin.NestedStackedPolymorphicInline.Child):
model = HourBuildingLegFlight
form = HourBuildingLegForm
class HourBuildingLegStopInLine(nested_admin.NestedStackedPolymorphicInline.Child):
model = HourBuildingLegStop
child_inlines = (HourBuildingLegFlightInLine, HourBuildingLegStopInLine, )
# 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):
@@ -45,26 +46,16 @@ class HourBuildingLegInline(nested_admin.NestedTabularInline):
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]
extra = 1
inlines = (HourBuildingLegBaseInLine,)
fk_name = 'weekpref'
verbose_name_plural = "Hour Building"
verbose_name_plural = "Hour Buildings"
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)

View File

@@ -18,8 +18,8 @@ from ..actions.exportweek import export_selected
from datetime import date
class WeekPreferenceAdmin(nested_admin.NestedModelAdmin):
inlines = (TrainingInLIne, HourBuildingInLine,)
class WeekPreferenceAdmin(nested_admin.NestedPolymorphicModelAdmin):
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",)

View File

@@ -0,0 +1,58 @@
# Generated by Django 5.2.8 on 2025-11-21 11:20
import datetime
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('flightslot', '0017_alter_missionprofile_mtype_alter_weekpreference_week'),
]
operations = [
migrations.CreateModel(
name='HourBuildingLegBase',
fields=[
('id', models.BigAutoField(primary_key=True, serialize=False)),
('time', models.DurationField(default=datetime.timedelta(seconds=3600))),
('hb', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='flightslot.hourbuilding')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
),
migrations.CreateModel(
name='HourBuildingLegFlight',
fields=[
('hourbuildinglegbase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='flightslot.hourbuildinglegbase')),
('departure', models.CharField(default='LILV', max_length=4)),
('destination', models.CharField(default='LILV', max_length=4)),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('flightslot.hourbuildinglegbase',),
),
migrations.CreateModel(
name='HourBuildingLegStop',
fields=[
('hourbuildinglegbase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='flightslot.hourbuildinglegbase')),
('location', models.CharField(default='LILV', max_length=4)),
('refuel', models.BooleanField(default=False)),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('flightslot.hourbuildinglegbase',),
),
migrations.DeleteModel(
name='HourBuildingLeg',
),
]

View File

@@ -2,10 +2,11 @@ from django.utils.translation import gettext_lazy as _
from django.db import models
from datetime import timedelta
from polymorphic.models import PolymorphicModel
from ..models.weekpref import WeekPreference
from ..models.aircrafts import AircraftTypes
class HourBuilding(models.Model):
id = models.BigAutoField(
primary_key=True
@@ -66,7 +67,7 @@ class HourBuilding(models.Model):
def __str__(self):
return f"Hour Building: {self.aircraft}"
class HourBuildingLeg(models.Model):
class HourBuildingLegBase(PolymorphicModel):
id = models.BigAutoField(
primary_key=True
)
@@ -76,6 +77,12 @@ class HourBuildingLeg(models.Model):
on_delete=models.CASCADE
)
time = models.DurationField(
null=False,
default = timedelta(hours=1)
)
class HourBuildingLegFlight(HourBuildingLegBase):
departure = models.CharField(
null=False,
blank=False,
@@ -90,18 +97,17 @@ class HourBuildingLeg(models.Model):
max_length=4
)
time = models.DurationField(
null=False,
default = timedelta(hours=1)
)
stop = models.BooleanField(
default=False
)
def __str__(self):
if self.stop:
return "Refuelling Stop"
else:
return f"Flight Leg: {self.departure} -> {self.destination}"
return f"Flight Leg: {self.departure} -> {self.destination}"
class HourBuildingLegStop(HourBuildingLegBase):
location = models.CharField(
null=False,
blank=False,
default="LILV",
max_length=4
)
refuel = models.BooleanField(
default=False
)

17
cntmanage/poetry.lock generated
View File

@@ -143,6 +143,21 @@ python-monkey-business = ">=1.0.0"
dev = ["Pillow", "black", "dj-database-url", "django-selenosis", "flake8", "pytest", "pytest-cov", "pytest-django", "pytest-xdist", "selenium"]
test = ["Pillow", "dj-database-url", "django-selenosis", "pytest", "pytest-cov", "pytest-django", "pytest-xdist", "selenium"]
[[package]]
name = "django-polymorphic"
version = "4.1.0"
description = "Seamless polymorphic inheritance for Django models"
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "django_polymorphic-4.1.0-py3-none-any.whl", hash = "sha256:0ce3984999e103a0d1a434a5c5617f2c7f990dc3d5fb3585ce0fadadf9ff90ea"},
{file = "django_polymorphic-4.1.0.tar.gz", hash = "sha256:4438d95a0aef6c4307cd6c83ead387e1142ce80b65188a931ec2f0dbdd9bfc51"},
]
[package.dependencies]
Django = ">=3.2"
[[package]]
name = "et-xmlfile"
version = "2.0.0"
@@ -421,4 +436,4 @@ files = [
[metadata]
lock-version = "2.1"
python-versions = "^3.12"
content-hash = "6bf43236f441d8b6bf8d1928910d169d3b29cfa499bb7d09d97ea227f8115658"
content-hash = "e932d0af75c888d83fecefaaad1d018c508881a3bfde2ea640a82790e3567855"

View File

@@ -17,6 +17,7 @@ django-import-export = "^4.3.13"
django-colorfield = "^0.14.0"
openpyxl = "^3.1.5"
django-admin-action-forms = "^2.2.1"
django-polymorphic = "^4.1.0"
[build-system]