From eb9018928f2165e472f7f93abb21f22e2b54fa0a Mon Sep 17 00:00:00 2001 From: Emanuele Date: Sun, 20 Oct 2024 10:46:19 +0200 Subject: [PATCH] Nested WeekPreference view in admin with nested_inline --- techdb/flightslot/admin.py | 23 ++- ..._training_missionprofile_notes_and_more.py | 65 ++++++ ...rbuilding_notes_training_notes_and_more.py | 39 ++++ techdb/flightslot/models.py | 191 +++++++++++++----- techdb/poetry.lock | 13 +- techdb/pyproject.toml | 1 + techdb/techdb/settings.py | 1 + 7 files changed, 281 insertions(+), 52 deletions(-) create mode 100644 techdb/flightslot/migrations/0004_rename_preference_training_missionprofile_notes_and_more.py create mode 100644 techdb/flightslot/migrations/0005_hourbuilding_notes_training_notes_and_more.py diff --git a/techdb/flightslot/admin.py b/techdb/flightslot/admin.py index 31bfbfa..e8d4780 100644 --- a/techdb/flightslot/admin.py +++ b/techdb/flightslot/admin.py @@ -1,15 +1,28 @@ from django.contrib import admin +from nested_inline.admin import NestedTabularInline, NestedModelAdmin from .models import * # Register your models here. admin.site.register(Student, StudentAdmin) admin.site.register(MissionProfile) -class PreferenceInLIne(admin.TabularInline): - model = Preference - extra = 0 +class HourBuildingLegInline(NestedTabularInline): + model = HourBuildingLeg + extra = 1 + fk_name = 'hb' -class WeekPreferenceAdmin(admin.ModelAdmin): - inlines = [PreferenceInLIne] +class HourBuildingInLine(NestedTabularInline): + model = HourBuilding + extra = 1 + inlines = [HourBuildingLegInline] + fk_name = 'weekpref' + +class TrainingInLIne(NestedTabularInline): + model = Training + extra = 0 + fk_name = 'weekpref' + +class WeekPreferenceAdmin(NestedModelAdmin): + inlines = [TrainingInLIne, HourBuildingInLine] admin.site.register(WeekPreference, WeekPreferenceAdmin) \ No newline at end of file diff --git a/techdb/flightslot/migrations/0004_rename_preference_training_missionprofile_notes_and_more.py b/techdb/flightslot/migrations/0004_rename_preference_training_missionprofile_notes_and_more.py new file mode 100644 index 0000000..3104a99 --- /dev/null +++ b/techdb/flightslot/migrations/0004_rename_preference_training_missionprofile_notes_and_more.py @@ -0,0 +1,65 @@ +# Generated by Django 5.1.2 on 2024-10-20 07:57 + +import django.db.models.deletion +import django.db.models.expressions +import django.db.models.functions.datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('flightslot', '0003_alter_missionprofile_mtype'), + ] + + operations = [ + migrations.RenameModel( + old_name='Preference', + new_name='Training', + ), + migrations.AddField( + model_name='missionprofile', + name='notes', + field=models.TextField(max_length=140, null=True), + ), + migrations.AlterField( + model_name='missionprofile', + name='duration', + field=models.DurationField(default=1), + ), + migrations.AlterField( + model_name='missionprofile', + name='mtype', + field=models.CharField(choices=[('OTHER', 'OTHER'), ('PPL', 'PPL'), ('IR', 'IR'), ('CPL', 'CPL'), ('FI', 'FI'), ('PC', 'PC'), ('CHK', 'CHK_6M')], default='PPL'), + ), + migrations.AlterField( + model_name='weekpreference', + name='week', + field=models.PositiveSmallIntegerField(auto_created=True, db_index=True, default=django.db.models.expressions.CombinedExpression(django.db.models.functions.datetime.ExtractWeek(django.db.models.functions.datetime.Now()), '+', models.Value(1))), + ), + migrations.CreateModel( + name='HourBuilding', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('aircraft', models.CharField(choices=[('C152', 'Cessna 152'), ('P208', 'Tecnam P2008'), ('PA28', 'Piper PA28R'), ('C182', 'Cessna 182Q'), ('P210', 'Tecnam P2010')])), + ('monday', models.BooleanField(default=True)), + ('tuesday', models.BooleanField(default=True)), + ('wednesday', models.BooleanField(default=True)), + ('thursday', models.BooleanField(default=True)), + ('saturday', models.BooleanField(default=True)), + ('sunday', models.BooleanField(default=True)), + ('weekpref', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='flightslot.weekpreference')), + ], + ), + migrations.CreateModel( + name='HourBuildingLeg', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('departure', models.CharField(default='LILV', max_length=4)), + ('destination', models.CharField(default='LILV', max_length=4)), + ('time', models.DurationField(default=1)), + ('stop', models.BooleanField(default=False)), + ('hb', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='flightslot.hourbuilding')), + ], + ), + ] diff --git a/techdb/flightslot/migrations/0005_hourbuilding_notes_training_notes_and_more.py b/techdb/flightslot/migrations/0005_hourbuilding_notes_training_notes_and_more.py new file mode 100644 index 0000000..afb35c3 --- /dev/null +++ b/techdb/flightslot/migrations/0005_hourbuilding_notes_training_notes_and_more.py @@ -0,0 +1,39 @@ +# Generated by Django 5.1.2 on 2024-10-20 08:28 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('flightslot', '0004_rename_preference_training_missionprofile_notes_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='hourbuilding', + name='notes', + field=models.TextField(max_length=140, null=True), + ), + migrations.AddField( + model_name='training', + name='notes', + field=models.TextField(max_length=140, null=True), + ), + migrations.AlterField( + model_name='hourbuilding', + name='weekpref', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='flightslot.weekpreference'), + ), + migrations.AlterField( + model_name='training', + name='mission', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='flightslot.missionprofile'), + ), + migrations.AlterField( + model_name='training', + name='weekpref', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='flightslot.weekpreference'), + ), + ] diff --git a/techdb/flightslot/models.py b/techdb/flightslot/models.py index 6c5bc96..a3274eb 100644 --- a/techdb/flightslot/models.py +++ b/techdb/flightslot/models.py @@ -1,6 +1,7 @@ from django.db import models from django.contrib import admin from django.db.models.functions import Now, ExtractWeek +from django.http import HttpRequest from django.utils.translation import gettext_lazy as _ # Create your models here. @@ -28,45 +29,6 @@ class Student(models.Model): max_length=32 ) - -class MissionType(models.TextChoices): - OTHER = "OTHER", _("OTHER") - HB = "HB", _("HB") - PPL = "PPL", _("PPL") - IR = "IR", _("IR") - CPL = "CPL", _("CPL") - FI = "FI", _("FI") - PC = "PC", _("PC") - CHK = "CHK", _("CHK_6M") - -class MissionProfile(models.Model): - - id = models.AutoField( - primary_key=True - ) - - mtype = models.CharField( - null=False, - default=MissionType.HB, - choices=MissionType - ) - - mnum = models.PositiveSmallIntegerField( - null=True, - default=0 - ) - - duration = models.DurationField( - null=False - ) - - def __str__(self): - if self.mtype is not MissionType.HB: - return f"{self.mtype}_{self.mnum}" - -class MissionProfileAdmin(admin.ModelAdmin): - list_display = ("mtype", "mnum") - class WeekPreference(models.Model): id = models.BigAutoField( primary_key=True @@ -75,7 +37,8 @@ class WeekPreference(models.Model): week = models.PositiveSmallIntegerField( null=False, db_index=True, - db_default=ExtractWeek(Now()) + 1 + default=ExtractWeek(Now()) + 1, + auto_created=True ) student = models.ForeignKey( @@ -85,8 +48,55 @@ class WeekPreference(models.Model): on_delete=models.DO_NOTHING ) +class MissionType(models.TextChoices): + OTHER = "OTHER", _("OTHER") + PPL = "PPL", _("PPL") + IR = "IR", _("IR") + CPL = "CPL", _("CPL") + FI = "FI", _("FI") + PC = "PC", _("PC") + CHK = "CHK", _("CHK_6M") -class Preference(models.Model): +class MissionProfile(models.Model): + id = models.AutoField( + primary_key=True + ) + + mtype = models.CharField( + null=False, + default=MissionType.PPL, + choices=MissionType + ) + + mnum = models.PositiveSmallIntegerField( + null=True, + default=0 + ) + + duration = models.DurationField( + null=False, + default=1 + ) + + notes = models.TextField( + max_length=140, + null=True + ) + + def __str__(self): + return f"{self.mtype} {self.mnum}" + +class MissionProfileAdmin(admin.ModelAdmin): + list_display = ("mtype", "mnum") + +class AircraftTypes(models.TextChoices): + C152 = "C152", _("Cessna 152") + P208 = "P208", _("Tecnam P2008") + PA28 = "PA28", _("Piper PA28R") + C182 = "C182", _("Cessna 182Q") + P210 = "P210", _("Tecnam P2010") + +class HourBuilding(models.Model): id = models.BigAutoField( primary_key=True ) @@ -94,13 +104,12 @@ class Preference(models.Model): weekpref = models.ForeignKey( WeekPreference, null=False, - on_delete=models.DO_NOTHING + on_delete=models.CASCADE ) - mission = models.ForeignKey( - MissionProfile, - null=True, - on_delete=models.DO_NOTHING + aircraft = models.CharField( + null=False, + choices=AircraftTypes ) monday = models.BooleanField( @@ -132,3 +141,93 @@ class Preference(models.Model): default=True, null=False ) + + notes = models.TextField( + max_length=140, + null=True + ) + +class HourBuildingLeg(models.Model): + id = models.BigAutoField( + primary_key=True + ) + + hb = models.ForeignKey( + HourBuilding, + on_delete=models.CASCADE + ) + + departure = models.CharField( + null=False, + blank=False, + default="LILV", + max_length=4 + ) + + destination = models.CharField( + null=False, + blank=False, + default="LILV", + max_length=4 + ) + + time = models.DurationField( + null=False, + default=1 + ) + + stop = models.BooleanField( + default=False + ) + +class Training(models.Model): + id = models.BigAutoField( + primary_key=True + ) + + weekpref = models.ForeignKey( + WeekPreference, + null=False, + on_delete=models.CASCADE + ) + + mission = models.ForeignKey( + MissionProfile, + null=True, + on_delete=models.CASCADE + ) + + 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 + ) + + saturday = models.BooleanField( + default=True, + null=False + ) + + sunday = models.BooleanField( + default=True, + null=False + ) + + notes = models.TextField( + max_length=140, + null=True + ) diff --git a/techdb/poetry.lock b/techdb/poetry.lock index ff27ed6..4ff8dae 100644 --- a/techdb/poetry.lock +++ b/techdb/poetry.lock @@ -34,6 +34,17 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""} argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] +[[package]] +name = "django-nested-inline" +version = "0.4.6" +description = "Recursive nesting of inline forms for Django Admin" +optional = false +python-versions = "*" +files = [ + {file = "django-nested-inline-0.4.6.tar.gz", hash = "sha256:e57b55858d112364dfb112bbcdabb888e581d1677d31c1cac3bdcef6c890dc61"}, + {file = "django_nested_inline-0.4.6-py2.py3-none-any.whl", hash = "sha256:4fc6f0e78b3b5411b4bb7f180bb984831b88874bda48e49a14307baff5da5f12"}, +] + [[package]] name = "psycopg2-binary" version = "2.9.10" @@ -139,4 +150,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "c3b2acd3f06588e63224efb9ff8fc91a396c95e22862e40427c05b788901ea24" +content-hash = "1ef37b219ab2fd51b8fa93268a04d3baea8cbaef61a470a6a01005f624510b21" diff --git a/techdb/pyproject.toml b/techdb/pyproject.toml index 2d51ed8..2b3b6f3 100644 --- a/techdb/pyproject.toml +++ b/techdb/pyproject.toml @@ -9,6 +9,7 @@ readme = "README.md" python = "^3.12" django = "^5.1.2" psycopg2-binary = "^2.9.10" +django-nested-inline = "^0.4.6" [build-system] diff --git a/techdb/techdb/settings.py b/techdb/techdb/settings.py index 57b6876..abb06c1 100644 --- a/techdb/techdb/settings.py +++ b/techdb/techdb/settings.py @@ -37,6 +37,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'nested_inline', 'catops', 'flightslot' ]