Compare commits
3 Commits
bcdc885d66
...
7ad09e21b7
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ad09e21b7 | |||
| 48ff1d799c | |||
| 02990d4b2f |
@@ -43,6 +43,7 @@ INSTALLED_APPS = [
|
|||||||
'colorfield',
|
'colorfield',
|
||||||
'import_export',
|
'import_export',
|
||||||
'django_admin_action_forms',
|
'django_admin_action_forms',
|
||||||
|
'polymorphic'
|
||||||
]
|
]
|
||||||
|
|
||||||
# Import Export plugin settings
|
# Import Export plugin settings
|
||||||
@@ -52,7 +53,7 @@ IMPORT_EXPORT_SKIP_ADMIN_LOG = True
|
|||||||
IMPORT_FORMATS = [CSV]
|
IMPORT_FORMATS = [CSV]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'flightslot.middleware.RedirectNonSuperuserFromAdminMiddleware',
|
'flightslot.middleware.RedirectNonSuperuserFromAdminMiddleware', # custom middleware to show "user" page to non superuser
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
|||||||
@@ -9,7 +9,3 @@ urlpatterns = [
|
|||||||
path('user/', flightslot_user.urls),
|
path('user/', flightslot_user.urls),
|
||||||
path("", lambda r: redirect("/user/")), # la root porta gli utenti nella pagina giusta
|
path("", lambda r: redirect("/user/")), # la root porta gli utenti nella pagina giusta
|
||||||
]
|
]
|
||||||
|
|
||||||
admin.site.site_header = "Flight Scheduler 🛫"
|
|
||||||
admin.site.site_title = "Flight Scheduler 🛫"
|
|
||||||
admin.site.index_title = "Welcome to CantorAir Flight Scheduler Portal"
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from typing import List
|
|||||||
|
|
||||||
from ..models.weekpref import WeekPreference
|
from ..models.weekpref import WeekPreference
|
||||||
from ..models.missions import Training
|
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:
|
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_name if h.sunday else ""
|
||||||
]
|
]
|
||||||
hb_notes = f"{h.notes}\n----\n" if h.notes else ""
|
hb_notes = f"{h.notes}\n----\n" if h.notes else ""
|
||||||
hb_legs = HourBuildingLeg.objects.filter(hb_id = h.id)
|
hb_legs = HourBuildingLegFlight.objects.filter(hb_id = h.id)
|
||||||
for hh in hb_legs:
|
#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 += 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_notes.strip('\n')
|
||||||
hb_data.append([str(q.week), *student_data, *hb_days, str(q.student.phone), q.student.email, hb_notes])
|
hb_data.append([str(q.week), *student_data, *hb_days, str(q.student.phone), q.student.email, hb_notes])
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from .admins.course_adm import CourseAdmin
|
|||||||
from .admins.student_adm import StudentAdmin
|
from .admins.student_adm import StudentAdmin
|
||||||
from .admins.mission_adm import MissionProfileAdmin
|
from .admins.mission_adm import MissionProfileAdmin
|
||||||
from .admins.weekpred_adm import WeekPreferenceAdmin
|
from .admins.weekpred_adm import WeekPreferenceAdmin
|
||||||
|
#from .admins.hourbuilding_adm import HourBuilding, HourBuildingInLine
|
||||||
|
|
||||||
from django.contrib.admin import AdminSite
|
from django.contrib.admin import AdminSite
|
||||||
|
|
||||||
@@ -31,6 +32,10 @@ flightslot_user = FlightSlotUserSite(name="user_site")
|
|||||||
# registra SOLO i modelli autorizzati
|
# registra SOLO i modelli autorizzati
|
||||||
flightslot_user.register(WeekPreference, WeekPreferenceAdmin)
|
flightslot_user.register(WeekPreference, WeekPreferenceAdmin)
|
||||||
|
|
||||||
|
admin.site.site_header = "Flight Scheduler Admin 🛫"
|
||||||
|
admin.site.site_title = "Flight Scheduler Admin 🛫"
|
||||||
|
admin.site.index_title = "Welcome to CantorAir Flight Scheduler Administrator Portal"
|
||||||
|
|
||||||
admin.site.register(Course, CourseAdmin)
|
admin.site.register(Course, CourseAdmin)
|
||||||
admin.site.register(MissionProfile, MissionProfileAdmin)
|
admin.site.register(MissionProfile, MissionProfileAdmin)
|
||||||
admin.site.register(Student, StudentAdmin)
|
admin.site.register(Student, StudentAdmin)
|
||||||
|
|||||||
@@ -7,36 +7,63 @@ from django.http import HttpRequest
|
|||||||
|
|
||||||
from durationwidget.widgets import TimeDurationWidget
|
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 ..models.weekpref import WeekPreference
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
class HourBuildingLegForm(forms.ModelForm):
|
class HourBuildingLegFlightForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = HourBuildingLeg
|
model = HourBuildingLegFlight
|
||||||
fields = '__all__'
|
fields = "__all__"
|
||||||
widgets = {
|
widgets = {
|
||||||
'time': TimeDurationWidget(show_days=False,
|
"time": TimeDurationWidget(show_days=False,
|
||||||
show_seconds=False
|
show_seconds=False,
|
||||||
|
attrs={
|
||||||
|
"style": (
|
||||||
|
"margin-right:5px; margin-left:5px; width:40px; min:0; max:5"
|
||||||
)
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
class HourBuildingLegStopForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = HourBuildingLegStop
|
||||||
|
fields = "__all__"
|
||||||
|
widgets = {
|
||||||
|
"time": TimeDurationWidget(show_days=False,
|
||||||
|
show_seconds=False,
|
||||||
|
attrs={
|
||||||
|
"style": (
|
||||||
|
"margin-right:5px; margin-left:5px; width:40px;"
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
class HourBuildingLegInline(nested_admin.NestedTabularInline):
|
class HourBuildingLegBaseInLine(nested_admin.NestedStackedPolymorphicInline):
|
||||||
model = HourBuildingLeg
|
model = HourBuildingLegBase
|
||||||
form = HourBuildingLegForm
|
fk_name = "hb"
|
||||||
extra = 0
|
verbose_name_plural = "Hour Building Legs"
|
||||||
fk_name = 'hb'
|
|
||||||
max_num = 5
|
class HourBuildingLegFlightInLine(nested_admin.NestedStackedPolymorphicInline.Child):
|
||||||
formfield_overrides = {
|
model = HourBuildingLegFlight
|
||||||
models.CharField: {'widget': TextInput(attrs={'size':'20'})},
|
form = HourBuildingLegFlightForm
|
||||||
models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':35})},
|
fk_name = "hourbuildinglegbase_ptr"
|
||||||
}
|
fields = ("departure", "time", "destination", "pax", )
|
||||||
|
hide_title = True
|
||||||
|
|
||||||
|
class HourBuildingLegStopInLine(nested_admin.NestedStackedPolymorphicInline.Child):
|
||||||
|
model = HourBuildingLegStop
|
||||||
|
form = HourBuildingLegFlightForm
|
||||||
|
fk_name = "hourbuildinglegbase_ptr"
|
||||||
|
fields = ("time", "refuel", )
|
||||||
|
|
||||||
|
child_inlines = (HourBuildingLegFlightInLine, HourBuildingLegStopInLine, )
|
||||||
|
|
||||||
# If user is a student deny edit permission for week past the current one
|
# 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):
|
def has_change_permission(self, request: HttpRequest, obj: HourBuilding | None = None):
|
||||||
if hasattr(request.user, 'student') and obj:
|
if hasattr(request.user, "student") and obj:
|
||||||
current_week = date.today().isocalendar().week
|
current_week = date.today().isocalendar().week
|
||||||
if not obj.DoesNotExist and current_week > obj.weekpref.week:
|
if not obj.DoesNotExist and current_week > obj.weekpref.week:
|
||||||
return False
|
return False
|
||||||
@@ -45,26 +72,16 @@ class HourBuildingLegInline(nested_admin.NestedTabularInline):
|
|||||||
def has_delete_permission(self, request: HttpRequest, obj: HourBuilding | None = None):
|
def has_delete_permission(self, request: HttpRequest, obj: HourBuilding | None = None):
|
||||||
return self.has_change_permission(request=request, obj=obj)
|
return self.has_change_permission(request=request, obj=obj)
|
||||||
|
|
||||||
|
|
||||||
class HourBuildingInLine(nested_admin.NestedTabularInline):
|
class HourBuildingInLine(nested_admin.NestedTabularInline):
|
||||||
model = HourBuilding
|
model = HourBuilding
|
||||||
|
inlines = (HourBuildingLegBaseInLine,)
|
||||||
extra = 0
|
extra = 0
|
||||||
inlines = [HourBuildingLegInline]
|
|
||||||
fk_name = 'weekpref'
|
|
||||||
verbose_name_plural = "Hour Building"
|
|
||||||
max_num = 7
|
max_num = 7
|
||||||
|
fk_name = "weekpref"
|
||||||
|
verbose_name_plural = "Hour Buildings"
|
||||||
formfield_overrides = {
|
formfield_overrides = {
|
||||||
models.CharField: {'widget': TextInput(attrs={'size':'20'})},
|
models.CharField: {"widget": TextInput(attrs={"size":"20"})},
|
||||||
models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':35})},
|
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)
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from ..actions.exportweek import export_selected
|
|||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
class WeekPreferenceAdmin(nested_admin.NestedModelAdmin):
|
class WeekPreferenceAdmin(nested_admin.NestedPolymorphicModelAdmin):
|
||||||
inlines = (TrainingInLIne, HourBuildingInLine, )
|
inlines = (TrainingInLIne, HourBuildingInLine, )
|
||||||
list_display = ("week", "student__surname","student__name", "student__course", "course_color", "student_brief_mix",)
|
list_display = ("week", "student__surname","student__name", "student__course", "course_color", "student_brief_mix",)
|
||||||
list_filter = ("week", "student__course", "student",)
|
list_filter = ("week", "student__course", "student",)
|
||||||
|
|||||||
@@ -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',
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Generated by Django 5.2.8 on 2025-11-21 16:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('flightslot', '0018_hourbuildinglegbase_hourbuildinglegflight_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='hourbuildinglegstop',
|
||||||
|
name='location',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='hourbuildinglegflight',
|
||||||
|
name='pax',
|
||||||
|
field=models.CharField(max_length=16, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='hourbuildinglegbase',
|
||||||
|
name='time',
|
||||||
|
field=models.DurationField(),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='hourbuildinglegflight',
|
||||||
|
name='departure',
|
||||||
|
field=models.CharField(max_length=4),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='hourbuildinglegflight',
|
||||||
|
name='destination',
|
||||||
|
field=models.CharField(max_length=4),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -2,10 +2,11 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from polymorphic.models import PolymorphicModel
|
||||||
|
|
||||||
from ..models.weekpref import WeekPreference
|
from ..models.weekpref import WeekPreference
|
||||||
from ..models.aircrafts import AircraftTypes
|
from ..models.aircrafts import AircraftTypes
|
||||||
|
|
||||||
|
|
||||||
class HourBuilding(models.Model):
|
class HourBuilding(models.Model):
|
||||||
id = models.BigAutoField(
|
id = models.BigAutoField(
|
||||||
primary_key=True
|
primary_key=True
|
||||||
@@ -66,7 +67,7 @@ class HourBuilding(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Hour Building: {self.aircraft}"
|
return f"Hour Building: {self.aircraft}"
|
||||||
|
|
||||||
class HourBuildingLeg(models.Model):
|
class HourBuildingLegBase(PolymorphicModel):
|
||||||
id = models.BigAutoField(
|
id = models.BigAutoField(
|
||||||
primary_key=True
|
primary_key=True
|
||||||
)
|
)
|
||||||
@@ -76,32 +77,54 @@ class HourBuildingLeg(models.Model):
|
|||||||
on_delete=models.CASCADE
|
on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
time = models.DurationField(
|
||||||
|
null=False
|
||||||
|
)
|
||||||
|
|
||||||
|
class HourBuildingLegFlight(HourBuildingLegBase):
|
||||||
departure = models.CharField(
|
departure = models.CharField(
|
||||||
null=False,
|
null=False,
|
||||||
blank=False,
|
blank=False,
|
||||||
default="LILV",
|
|
||||||
max_length=4
|
max_length=4
|
||||||
)
|
)
|
||||||
|
|
||||||
destination = models.CharField(
|
destination = models.CharField(
|
||||||
null=False,
|
null=False,
|
||||||
blank=False,
|
blank=False,
|
||||||
default="LILV",
|
|
||||||
max_length=4
|
max_length=4
|
||||||
)
|
)
|
||||||
|
|
||||||
time = models.DurationField(
|
pax = models.CharField(
|
||||||
null=False,
|
null=True,
|
||||||
default = timedelta(hours=1)
|
blank=True,
|
||||||
|
max_length=16,
|
||||||
|
verbose_name="Pax (optional)"
|
||||||
)
|
)
|
||||||
|
|
||||||
stop = models.BooleanField(
|
# Change displayed name in the inline form
|
||||||
|
class Meta(PolymorphicModel.Meta):
|
||||||
|
verbose_name = "Flight leg"
|
||||||
|
verbose_name_plural = "Flight legs"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.departure} -> {self.destination}"
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.departure = self.departure.capitalize().strip()
|
||||||
|
self.destination = self.destination.capitalize().strip()
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
class HourBuildingLegStop(HourBuildingLegBase):
|
||||||
|
|
||||||
|
refuel = models.BooleanField(
|
||||||
default=False
|
default=False
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
# Change displayed name in the inline form
|
||||||
if self.stop:
|
class Meta(PolymorphicModel.Meta):
|
||||||
return "Refuelling Stop"
|
verbose_name = "Stop"
|
||||||
else:
|
verbose_name_plural = "Stops"
|
||||||
return f"Flight Leg: {self.departure} -> {self.destination}"
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Refuel" if self.refuel else f"No Refuel"
|
||||||
|
|
||||||
@@ -51,24 +51,24 @@ class Student(models.Model):
|
|||||||
|
|
||||||
# Override save method to add user for login upon Student creation
|
# Override save method to add user for login upon Student creation
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
creating = self.pk is None
|
creating: bool = self.pk is None
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
if creating and not self.user:
|
if creating and not self.user:
|
||||||
username = f"{self.name.lower()}.{self.surname.lower()}"
|
username: str = f"{self.name.lower()}.{self.surname.lower()}"
|
||||||
# Avoid username conflict with progressive number
|
# Avoid username conflict with progressive number
|
||||||
base_username = username
|
base_username = username
|
||||||
counter = 1
|
counter: int = 1
|
||||||
while User.objects.filter(username=username).exists():
|
while User.objects.filter(username=username).exists():
|
||||||
username = f"{base_username}{counter}"
|
username = f"{base_username}{counter}"
|
||||||
counter += 1
|
counter += 1
|
||||||
# Create user
|
# Create user
|
||||||
user = User.objects.create_user(
|
user: User = User.objects.create_user(
|
||||||
first_name=self.name,
|
first_name=self.name,
|
||||||
last_name=self.surname,
|
last_name=self.surname,
|
||||||
username=username,
|
username=username,
|
||||||
email=self.email,
|
email=self.email,
|
||||||
password=self.default_password(),
|
password=self.default_password(),
|
||||||
is_staff=True
|
is_staff=True # allows access to admin page
|
||||||
)
|
)
|
||||||
|
|
||||||
student_group, _ = Group.objects.get_or_create(name="StudentGroup")
|
student_group, _ = Group.objects.get_or_create(name="StudentGroup")
|
||||||
|
|||||||
23
cntmanage/poetry.lock
generated
23
cntmanage/poetry.lock
generated
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asgiref"
|
name = "asgiref"
|
||||||
version = "3.10.0"
|
version = "3.11.0"
|
||||||
description = "ASGI specs, helper code, and adapters"
|
description = "ASGI specs, helper code, and adapters"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "asgiref-3.10.0-py3-none-any.whl", hash = "sha256:aef8a81283a34d0ab31630c9b7dfe70c812c95eba78171367ca8745e88124734"},
|
{file = "asgiref-3.11.0-py3-none-any.whl", hash = "sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d"},
|
||||||
{file = "asgiref-3.10.0.tar.gz", hash = "sha256:d89f2d8cd8b56dada7d52fa7dc8075baa08fb836560710d38c292a7a3f78c04e"},
|
{file = "asgiref-3.11.0.tar.gz", hash = "sha256:13acff32519542a1736223fb79a715acdebe24286d98e8b164a73085f40da2c4"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@@ -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"]
|
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"]
|
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]]
|
[[package]]
|
||||||
name = "et-xmlfile"
|
name = "et-xmlfile"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@@ -421,4 +436,4 @@ files = [
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.1"
|
lock-version = "2.1"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.12"
|
||||||
content-hash = "6bf43236f441d8b6bf8d1928910d169d3b29cfa499bb7d09d97ea227f8115658"
|
content-hash = "e932d0af75c888d83fecefaaad1d018c508881a3bfde2ea640a82790e3567855"
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ django-import-export = "^4.3.13"
|
|||||||
django-colorfield = "^0.14.0"
|
django-colorfield = "^0.14.0"
|
||||||
openpyxl = "^3.1.5"
|
openpyxl = "^3.1.5"
|
||||||
django-admin-action-forms = "^2.2.1"
|
django-admin-action-forms = "^2.2.1"
|
||||||
|
django-polymorphic = "^4.1.0"
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
|
|||||||
Reference in New Issue
Block a user