Files
Netbox-Utilities/netbox_utilities/forms.py
T

142 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from dcim.choices import ModuleStatusChoices
from dcim.models import Device, ModuleBay, ModuleType
from django import forms
from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField
from .models import UtilitiesSettings
class BulkModuleInstallForm(forms.Form):
device = DynamicModelChoiceField(
label="Gerät",
queryset=Device.objects.all(),
selector=True,
)
module_type = DynamicModelChoiceField(
label="Modultyp",
queryset=ModuleType.objects.all(),
context={"parent": "manufacturer"},
selector=True,
)
module_bays = DynamicModelMultipleChoiceField(
label="Modulschächte",
queryset=ModuleBay.objects.all(),
required=False,
query_params={"device_id": "$device"},
context={"disabled": "_occupied"},
help_text="Bestimmte freie Schächte auswählen. Alternativ kann die Anzahl verwendet werden.",
)
quantity = forms.IntegerField(
label="Anzahl (1x)",
required=False,
min_value=1,
help_text=(
"Baut die angegebene Anzahl automatisch in die ersten freien Modulschächte ein. "
"Nicht zusammen mit einer manuellen Schachtauswahl verwenden."
),
)
status = forms.ChoiceField(
label="Status",
choices=ModuleStatusChoices,
initial=ModuleStatusChoices.STATUS_ACTIVE,
)
replicate_components = forms.BooleanField(
label="Komponenten replizieren",
required=False,
initial=True,
help_text="Komponenten aus den Vorlagen des Modultyps automatisch anlegen.",
)
description = forms.CharField(
label="Beschreibung",
required=False,
widget=forms.Textarea(attrs={"rows": 3}),
)
def __init__(self, *args, user, **kwargs):
super().__init__(*args, **kwargs)
self.fields["device"].queryset = Device.objects.restrict(user, "view")
self.fields["module_type"].queryset = ModuleType.objects.restrict(user, "view")
module_bays = ModuleBay.objects.restrict(user, "view").filter(
enabled=True,
installed_module__isnull=True,
)
device = self.data.get("device") or self.initial.get("device")
if isinstance(device, Device):
device = device.pk
if device:
module_bays = module_bays.filter(device_id=device)
self.available_module_bays = module_bays
self.fields["module_bays"].queryset = module_bays
def clean(self):
cleaned_data = super().clean()
device = cleaned_data.get("device")
module_bays = cleaned_data.get("module_bays")
quantity = cleaned_data.get("quantity")
if module_bays and quantity:
self.add_error("quantity", "Anzahl und manuelle Schachtauswahl können nicht kombiniert werden.")
elif not module_bays and not quantity and "module_bays" not in self.errors and "quantity" not in self.errors:
self.add_error(None, "Wählen Sie Modulschächte aus oder geben Sie eine Anzahl ein.")
elif quantity and device:
available_bays = self.available_module_bays
available_count = available_bays.count()
if quantity > available_count:
availability = (
"nur ein freier Modulschacht"
if available_count == 1
else f"nur {available_count} freie Modulschächte"
)
self.add_error(
"quantity",
f"Für dieses Gerät sind {availability} verfügbar.",
)
else:
cleaned_data["module_bays"] = list(available_bays[:quantity])
if device and module_bays:
invalid_bays = [
module_bay.name
for module_bay in module_bays
if module_bay.device_id != device.pk
or not module_bay.enabled
or hasattr(module_bay, "installed_module")
]
if invalid_bays:
self.add_error(
"module_bays",
"Diese Modulschächte sind nicht frei oder gehören nicht zum gewählten Gerät: "
+ ", ".join(invalid_bays),
)
return cleaned_data
class UtilitiesSettingsForm(forms.ModelForm):
def __init__(self, *args, tenant_filter_locked=False, tenant_required_locked=False, **kwargs):
super().__init__(*args, **kwargs)
self.fields["tenant_filter_enabled"].disabled = tenant_filter_locked
self.fields["tenant_required"].disabled = tenant_required_locked
class Meta:
model = UtilitiesSettings
fields = ("tenant_filter_enabled", "tenant_required")
labels = {
"tenant_filter_enabled": "Globalen Mandantenfilter aktivieren",
"tenant_required": "Mandant für mandantenfähige Objekte verpflichtend machen",
}
help_texts = {
"tenant_filter_enabled": (
"Blendet das Mandanten-Dropdown ein und ergänzt unterstützte NetBox-Listen "
"automatisch um den gewählten Mandantenfilter."
),
"tenant_required": (
"Verhindert das Speichern mandantenfähiger Objekte ohne Mandant. "
"Dies gilt auch für Importe, API-Aufrufe und Skripte."
),
}
widgets = {
"tenant_filter_enabled": forms.CheckboxInput(attrs={"class": "form-check-input"}),
"tenant_required": forms.CheckboxInput(attrs={"class": "form-check-input"}),
}