From 60bcf5c266f3527b4ff27352f8421f3185c3fdf9 Mon Sep 17 00:00:00 2001
From: Ben Burwood <77846694+benbur98@users.noreply.github.com>
Date: Mon, 8 Jul 2024 19:10:08 +0100
Subject: [PATCH] Rack Management (#10)
* Add Rack and RackItem Models and Forms
* Add Views and URLs
* Add Template Pages
* MakeMigrations for Rack and RackItem
* Migrate to Abstract Device Model for Client/Network Devices
* Link RackItem and Network Device
* Bugfixes
* More Bugfixes
* Generalise Device Create and Index Pages
for Client and Network Devices
* Delete Admin/Test Files
* Rack Measure Conversions and Index
* Add Networked vs Infrastructure Devices
* Forms Folder for Network App
* Make Migrations for Network Devices
---
common/templates/base/crud.html | 4 +
common/templates/base/sidebar.html | 1 +
common/utils/units.py | 8 ++
electric/admin.py | 3 -
.../0002_alter_circuit_breaker_type.py | 27 ++++++
.../0003_alter_circuit_breaker_type.py | 27 ++++++
electric/templates/electric/index.html | 4 +
electric/tests.py | 3 -
home/admin.py | 3 -
home/tests.py | 3 -
mqtt/admin.py | 3 -
mqtt/tests.py | 3 -
network/admin.py | 3 -
network/forms.py | 58 ------------
network/forms/__init__.py | 0
network/forms/devices.py | 63 +++++++++++++
network/forms/networking.py | 27 ++++++
network/forms/rack.py | 23 +++++
network/migrations/0002_rack_rackitem.py | 60 +++++++++++++
...r_clientdevice_connection_type_and_more.py | 90 +++++++++++++++++++
network/migrations/0004_rackitem_device.py | 25 ++++++
...edevice_alter_networkdevice_device_type.py | 57 ++++++++++++
network/models/__init__.py | 3 +-
network/models/client_device.py | 35 --------
network/models/device.py | 55 ++++++++++++
network/models/rack.py | 68 ++++++++++++++
network/objects.py | 36 ++++++++
.../device/{edit.html => client_edit.html} | 2 +-
network/templates/network/device/create.html | 48 ++++++++--
network/templates/network/device/index.html | 26 +++++-
.../network/device/network_edit.html | 17 ++++
network/templates/network/rack/create.html | 17 ++++
network/templates/network/rack/edit.html | 17 ++++
network/templates/network/rack/index.html | 47 ++++++++++
.../templates/network/rack_item/create.html | 17 ++++
network/templates/network/rack_item/edit.html | 17 ++++
.../templates/network/rack_item/index.html | 35 ++++++++
network/tests.py | 3 -
network/urls.py | 85 +++++++++++++++---
network/views/__init__.py | 2 +-
network/views/device.py | 63 ++++++++++---
network/views/rack.py | 84 +++++++++++++++++
network/views/vlan.py | 3 +-
network/views/wifi.py | 3 +-
44 files changed, 1019 insertions(+), 159 deletions(-)
create mode 100644 common/utils/units.py
delete mode 100644 electric/admin.py
create mode 100644 electric/migrations/0002_alter_circuit_breaker_type.py
create mode 100644 electric/migrations/0003_alter_circuit_breaker_type.py
delete mode 100644 electric/tests.py
delete mode 100644 home/admin.py
delete mode 100644 home/tests.py
delete mode 100644 mqtt/admin.py
delete mode 100644 mqtt/tests.py
delete mode 100644 network/admin.py
delete mode 100644 network/forms.py
create mode 100644 network/forms/__init__.py
create mode 100644 network/forms/devices.py
create mode 100644 network/forms/networking.py
create mode 100644 network/forms/rack.py
create mode 100644 network/migrations/0002_rack_rackitem.py
create mode 100644 network/migrations/0003_alter_clientdevice_connection_type_and_more.py
create mode 100644 network/migrations/0004_rackitem_device.py
create mode 100644 network/migrations/0005_infrastructuredevice_alter_networkdevice_device_type.py
delete mode 100644 network/models/client_device.py
create mode 100644 network/models/device.py
create mode 100644 network/models/rack.py
create mode 100644 network/objects.py
rename network/templates/network/device/{edit.html => client_edit.html} (86%)
create mode 100644 network/templates/network/device/network_edit.html
create mode 100644 network/templates/network/rack/create.html
create mode 100644 network/templates/network/rack/edit.html
create mode 100644 network/templates/network/rack/index.html
create mode 100644 network/templates/network/rack_item/create.html
create mode 100644 network/templates/network/rack_item/edit.html
create mode 100644 network/templates/network/rack_item/index.html
delete mode 100644 network/tests.py
create mode 100644 network/views/rack.py
diff --git a/common/templates/base/crud.html b/common/templates/base/crud.html
index 13d8c9b..2718590 100644
--- a/common/templates/base/crud.html
+++ b/common/templates/base/crud.html
@@ -15,11 +15,15 @@
{% block header_content %}{% endblock %}
Back
+ {% if show_form|default:"True" %}
+ {% endif %}
+
+ {% block additional_content %}{% endblock %}
diff --git a/common/templates/base/sidebar.html b/common/templates/base/sidebar.html
index 1376ae3..3bb911b 100644
--- a/common/templates/base/sidebar.html
+++ b/common/templates/base/sidebar.html
@@ -8,6 +8,7 @@
VLAN
WiFi
Devices
+ Racks
MQTT
diff --git a/common/utils/units.py b/common/utils/units.py
new file mode 100644
index 0000000..9c024a7
--- /dev/null
+++ b/common/utils/units.py
@@ -0,0 +1,8 @@
+def mm_to_inch(mm: float) -> float:
+ """Convert mm to Inches"""
+ return mm / 25.4
+
+
+def inch_to_mm(inch: float) -> float:
+ """Convert Inches to mm"""
+ return inch * 25.4
diff --git a/electric/admin.py b/electric/admin.py
deleted file mode 100644
index 8c38f3f..0000000
--- a/electric/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/electric/migrations/0002_alter_circuit_breaker_type.py b/electric/migrations/0002_alter_circuit_breaker_type.py
new file mode 100644
index 0000000..4555b4d
--- /dev/null
+++ b/electric/migrations/0002_alter_circuit_breaker_type.py
@@ -0,0 +1,27 @@
+# Generated by Django 5.0.2 on 2024-06-06 18:30
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("electric", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="circuit",
+ name="breaker_type",
+ field=models.CharField(
+ choices=[
+ ("fuse", "Fuse"),
+ ("mcb", "MCB"),
+ ("rcd", "RCD"),
+ ("RCBO", "rcbo"),
+ ("gfci", "GFCI"),
+ ],
+ max_length=10,
+ ),
+ ),
+ ]
diff --git a/electric/migrations/0003_alter_circuit_breaker_type.py b/electric/migrations/0003_alter_circuit_breaker_type.py
new file mode 100644
index 0000000..bfc3c4c
--- /dev/null
+++ b/electric/migrations/0003_alter_circuit_breaker_type.py
@@ -0,0 +1,27 @@
+# Generated by Django 5.0.2 on 2024-07-08 18:08
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("electric", "0002_alter_circuit_breaker_type"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="circuit",
+ name="breaker_type",
+ field=models.CharField(
+ choices=[
+ ("fuse", "Fuse"),
+ ("mcb", "MCB"),
+ ("rcd", "RCD"),
+ ("rcbo", "RCBO"),
+ ("gfci", "GFCI"),
+ ],
+ max_length=10,
+ ),
+ ),
+ ]
diff --git a/electric/templates/electric/index.html b/electric/templates/electric/index.html
index 048657c..f76634c 100644
--- a/electric/templates/electric/index.html
+++ b/electric/templates/electric/index.html
@@ -20,6 +20,10 @@ Voltage
+
+
+
+ Circuits
diff --git a/electric/tests.py b/electric/tests.py
deleted file mode 100644
index 7ce503c..0000000
--- a/electric/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/home/admin.py b/home/admin.py
deleted file mode 100644
index 8c38f3f..0000000
--- a/home/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/home/tests.py b/home/tests.py
deleted file mode 100644
index 7ce503c..0000000
--- a/home/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/mqtt/admin.py b/mqtt/admin.py
deleted file mode 100644
index 8c38f3f..0000000
--- a/mqtt/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/mqtt/tests.py b/mqtt/tests.py
deleted file mode 100644
index 7ce503c..0000000
--- a/mqtt/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/network/admin.py b/network/admin.py
deleted file mode 100644
index 8c38f3f..0000000
--- a/network/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/network/forms.py b/network/forms.py
deleted file mode 100644
index 8fa3447..0000000
--- a/network/forms.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from django import forms
-
-from .models import ClientDevice, VLAN, WifiNetwork
-from .models.ip import IpRange
-
-class IpRangeForm(forms.Form):
-
- description = forms.CharField(widget=forms.Textarea(attrs={"style": "height:50px;"}), required=False)
-
- class Meta:
- model = IpRange
- fields = ["start_address", "end_address", "num_addresses", "description"]
-
-
-class VLANForm(forms.ModelForm):
-
- description = forms.CharField(widget=forms.Textarea(attrs={"style": "height:50px;"}), required=False)
-
- class Meta:
- model = VLAN
- fields = ["vlan_id", "name", "description"]
-
-
-class WifiForm(forms.ModelForm):
- class Meta:
- model = WifiNetwork
- fields = ["ssid", "password"]
-
-
-class ClientDeviceForm(forms.ModelForm):
-
- connection_type = forms.ChoiceField(choices=ClientDevice.CONNECTION_TYPES, widget=forms.Select(attrs={"class": "form-control"}))
-
- class Meta:
- model = ClientDevice
- fields = ["name", "mac_address", "vlan", "ip_address", "connection_type", "wifi"]
-
- def __init__(self, *args, vlan_options=None, wifi_options=None, **kwargs):
- super(ClientDeviceForm, self).__init__(*args, **kwargs)
-
- self.fields["vlan"].widget = forms.Select(choices=vlan_options, attrs={"class": "form-control"})
-
- empty_choice = [("", "None")]
-
- self.fields["wifi"].widget = forms.Select(choices=empty_choice + wifi_options, attrs={"class": "form-control"})
- self.fields["wifi"].required = False
-
- def clean(self):
- cleaned_data = super().clean()
-
- connection_type = cleaned_data.get("connection_type")
- wifi = cleaned_data.get("wifi")
- if connection_type == "ethernet" and wifi:
- raise forms.ValidationError("WiFi must be null for Ethernet Connections", code="invalid")
- if connection_type == "wifi" and not wifi:
- raise forms.ValidationError("WiFi must be set for WiFi Connections", code="invalid")
-
- return cleaned_data
diff --git a/network/forms/__init__.py b/network/forms/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/network/forms/devices.py b/network/forms/devices.py
new file mode 100644
index 0000000..348da2c
--- /dev/null
+++ b/network/forms/devices.py
@@ -0,0 +1,63 @@
+from django import forms
+
+from network.models import ClientDevice, NetworkDevice
+from network.models.device import InfrastructureDevice, NetworkedDevice
+from network.objects import ConnectionType
+
+class NetworkedDeviceForm(forms.ModelForm):
+
+ connection_type = forms.ChoiceField(
+ choices=ConnectionType.choices(),
+ widget=forms.Select(attrs={"class": "form-control"}),
+ )
+
+ class Meta:
+ model = NetworkedDevice
+ abstract = True
+ fields = [
+ "name",
+ "mac_address",
+ "vlan",
+ "ip_address",
+ "connection_type",
+ "wifi",
+ ]
+
+ def __init__(self, *args, vlan_options=None, wifi_options=None, **kwargs):
+ super(NetworkedDeviceForm, self).__init__(*args, **kwargs)
+
+ self.fields["vlan"].widget = forms.Select(choices=vlan_options, attrs={"class": "form-control"})
+
+ empty_choice = [("", "None")]
+
+ self.fields["wifi"].widget = forms.Select(choices=empty_choice + wifi_options, attrs={"class": "form-control"})
+ self.fields["wifi"].required = False
+
+ def clean(self):
+ cleaned_data = super().clean()
+
+ connection_type = cleaned_data.get("connection_type")
+ wifi = cleaned_data.get("wifi")
+ if connection_type == "ethernet" and wifi:
+ raise forms.ValidationError("WiFi must be null for Ethernet Connections", code="invalid")
+ if connection_type == "wifi" and not wifi:
+ raise forms.ValidationError("WiFi must be set for WiFi Connections", code="invalid")
+
+ return cleaned_data
+
+
+class ClientDeviceForm(NetworkedDeviceForm):
+ class Meta(NetworkedDeviceForm.Meta):
+ model = ClientDevice
+
+
+class NetworkDeviceForm(NetworkedDeviceForm):
+ class Meta(NetworkedDeviceForm.Meta):
+ model = NetworkDevice
+ fields = NetworkedDeviceForm.Meta.fields + ["device_type"]
+
+
+class InfrastructureDeviceForm(forms.ModelForm):
+ class Meta:
+ model = InfrastructureDevice
+ fields = ["name", "device_type"]
diff --git a/network/forms/networking.py b/network/forms/networking.py
new file mode 100644
index 0000000..da40971
--- /dev/null
+++ b/network/forms/networking.py
@@ -0,0 +1,27 @@
+from django import forms
+
+from network.models import VLAN, WifiNetwork
+from network.models.ip import IpRange
+
+class IpRangeForm(forms.Form):
+
+ description = forms.CharField(widget=forms.Textarea(attrs={"style": "height:50px;"}), required=False)
+
+ class Meta:
+ model = IpRange
+ fields = ["start_address", "end_address", "num_addresses", "description"]
+
+
+class VLANForm(forms.ModelForm):
+
+ description = forms.CharField(widget=forms.Textarea(attrs={"style": "height:50px;"}), required=False)
+
+ class Meta:
+ model = VLAN
+ fields = ["vlan_id", "name", "description"]
+
+
+class WifiForm(forms.ModelForm):
+ class Meta:
+ model = WifiNetwork
+ fields = ["ssid", "password"]
diff --git a/network/forms/rack.py b/network/forms/rack.py
new file mode 100644
index 0000000..380e457
--- /dev/null
+++ b/network/forms/rack.py
@@ -0,0 +1,23 @@
+from django import forms
+
+from network.models import Rack, RackItem
+
+class RackForm(forms.ModelForm):
+
+ class Meta:
+ model = Rack
+ fields = ["name", "width", "rack_units"]
+
+
+class RackItemForm(forms.ModelForm):
+
+ class Meta:
+ model = RackItem
+ fields = ["name", "rack_units", "rack", "device"]
+
+ def __init__(self, *args, rack_options=None, device_options=None, **kwargs):
+ super(RackItemForm, self).__init__(*args, **kwargs)
+
+ self.fields["rack"].widget = forms.Select(choices=rack_options, attrs={"class": "form-control"})
+
+ self.fields["device"].widget = forms.Select(choices=device_options, attrs={"class": "form-control"})
diff --git a/network/migrations/0002_rack_rackitem.py b/network/migrations/0002_rack_rackitem.py
new file mode 100644
index 0000000..9bfd22e
--- /dev/null
+++ b/network/migrations/0002_rack_rackitem.py
@@ -0,0 +1,60 @@
+# Generated by Django 5.0.2 on 2024-06-06 18:05
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("network", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="Rack",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("name", models.CharField(max_length=50)),
+ (
+ "width",
+ models.PositiveIntegerField(
+ choices=[(10, "WIDTH_10"), (19, "WIDTH_19"), (23, "WIDTH_23")]
+ ),
+ ),
+ ("rack_units", models.FloatField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name="RackItem",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("name", models.CharField(max_length=50)),
+ ("rack_units", models.FloatField()),
+ (
+ "rack",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="rack_items",
+ to="network.rack",
+ ),
+ ),
+ ],
+ ),
+ ]
diff --git a/network/migrations/0003_alter_clientdevice_connection_type_and_more.py b/network/migrations/0003_alter_clientdevice_connection_type_and_more.py
new file mode 100644
index 0000000..f807f7e
--- /dev/null
+++ b/network/migrations/0003_alter_clientdevice_connection_type_and_more.py
@@ -0,0 +1,90 @@
+# Generated by Django 5.0.2 on 2024-06-06 18:18
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("network", "0002_rack_rackitem"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="clientdevice",
+ name="connection_type",
+ field=models.CharField(
+ choices=[("ETHERNET", "Ethernet"), ("WIFI", "Wifi")], max_length=10
+ ),
+ ),
+ migrations.AlterField(
+ model_name="clientdevice",
+ name="vlan",
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ to="network.vlan",
+ ),
+ ),
+ migrations.CreateModel(
+ name="NetworkDevice",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("name", models.CharField(max_length=100)),
+ ("mac_address", models.CharField(max_length=17, unique=True)),
+ (
+ "ip_address",
+ models.GenericIPAddressField(blank=True, null=True, unique=True),
+ ),
+ (
+ "connection_type",
+ models.CharField(
+ choices=[("ETHERNET", "Ethernet"), ("WIFI", "Wifi")],
+ max_length=10,
+ ),
+ ),
+ (
+ "device_type",
+ models.CharField(
+ choices=[
+ ("ROUTER", "Router"),
+ ("SWITCH", "Switch"),
+ ("ACCESS_POINT", "Access_point"),
+ ],
+ max_length=20,
+ ),
+ ),
+ (
+ "vlan",
+ models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ to="network.vlan",
+ ),
+ ),
+ (
+ "wifi",
+ models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ to="network.wifinetwork",
+ ),
+ ),
+ ],
+ options={
+ "abstract": False,
+ },
+ ),
+ ]
diff --git a/network/migrations/0004_rackitem_device.py b/network/migrations/0004_rackitem_device.py
new file mode 100644
index 0000000..d4a347c
--- /dev/null
+++ b/network/migrations/0004_rackitem_device.py
@@ -0,0 +1,25 @@
+# Generated by Django 5.0.2 on 2024-06-06 18:20
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("network", "0003_alter_clientdevice_connection_type_and_more"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="rackitem",
+ name="device",
+ field=models.OneToOneField(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="rack_item",
+ to="network.networkdevice",
+ ),
+ ),
+ ]
diff --git a/network/migrations/0005_infrastructuredevice_alter_networkdevice_device_type.py b/network/migrations/0005_infrastructuredevice_alter_networkdevice_device_type.py
new file mode 100644
index 0000000..41a8850
--- /dev/null
+++ b/network/migrations/0005_infrastructuredevice_alter_networkdevice_device_type.py
@@ -0,0 +1,57 @@
+# Generated by Django 5.0.2 on 2024-07-08 18:08
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("network", "0004_rackitem_device"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="InfrastructureDevice",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("name", models.CharField(max_length=100)),
+ (
+ "device_type",
+ models.CharField(
+ choices=[
+ ("POWER", "Power"),
+ ("PATCH_PANEL", "Patch_panel"),
+ ("BLANK", "Blank"),
+ ("CABLE_MANAGEMENT", "Cable_management"),
+ ],
+ max_length=20,
+ ),
+ ),
+ ],
+ options={
+ "abstract": False,
+ },
+ ),
+ migrations.AlterField(
+ model_name="networkdevice",
+ name="device_type",
+ field=models.CharField(
+ choices=[
+ ("ROUTER", "Router"),
+ ("FIREWALL", "Firewall"),
+ ("SWITCH", "Switch"),
+ ("ACCESS_POINT", "Access_point"),
+ ("STORAGE", "Storage"),
+ ],
+ max_length=20,
+ ),
+ ),
+ ]
diff --git a/network/models/__init__.py b/network/models/__init__.py
index bf01afd..430ce82 100644
--- a/network/models/__init__.py
+++ b/network/models/__init__.py
@@ -1,3 +1,4 @@
-from .client_device import ClientDevice
+from .device import ClientDevice, NetworkDevice
+from .rack import Rack, RackItem
from .vlan import VLAN
from .wifi import WifiNetwork
diff --git a/network/models/client_device.py b/network/models/client_device.py
deleted file mode 100644
index 74964c8..0000000
--- a/network/models/client_device.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import re
-
-from django.core.exceptions import ValidationError
-from django.db import models
-
-from .vlan import VLAN
-from .wifi import WifiNetwork
-
-
-class ClientDevice(models.Model):
- CONNECTION_TYPES = (
- ("ethernet", "Ethernet"),
- ("wifi", "WiFi"),
- )
-
- name = models.CharField(max_length=100)
- mac_address = models.CharField(max_length=17, unique=True)
- ip_address = models.GenericIPAddressField(blank=True, null=True, unique=True)
- vlan = models.ForeignKey(VLAN, on_delete=models.CASCADE)
- wifi = models.ForeignKey(WifiNetwork, on_delete=models.CASCADE, blank=True, null=True)
- connection_type = models.CharField(max_length=10, choices=CONNECTION_TYPES)
-
- def __str__(self):
- return self.name
-
- def clean(self):
- super().clean()
-
- if not self.mac_address_validation(self.mac_address):
- raise ValidationError("Invalid MAC Address format")
-
- @staticmethod
- def mac_address_validation(mac_address: str) -> bool:
- MAC_ADDRESS_PATTERN = r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})|([0-9a-fA-F]{4}\.[0-9a-fA-F]{4}\.[0-9a-fA-F]{4})$"
- return re.match(MAC_ADDRESS_PATTERN, mac_address) is not None
diff --git a/network/models/device.py b/network/models/device.py
new file mode 100644
index 0000000..ccfb79f
--- /dev/null
+++ b/network/models/device.py
@@ -0,0 +1,55 @@
+import re
+
+from django.core.exceptions import ValidationError
+from django.db import models
+
+from network.models.vlan import VLAN
+from network.models.wifi import WifiNetwork
+from network.objects import ConnectionType, InfrastructureDeviceType, NetworkDeviceType
+
+class Device(models.Model):
+ """Generic Device with a Name"""
+
+ name = models.CharField(max_length=100)
+
+ def __str__(self):
+ return self.name
+
+ class Meta:
+ abstract = True
+
+
+class NetworkedDevice(Device):
+ """Networked Device with MAC Address, IP Address, VLAN, and Connection Type (and/or WiFi Network)"""
+
+ mac_address = models.CharField(max_length=17, unique=True)
+ ip_address = models.GenericIPAddressField(blank=True, null=True, unique=True)
+ vlan = models.ForeignKey(VLAN, on_delete=models.CASCADE, blank=True, null=True)
+ wifi = models.ForeignKey(WifiNetwork, on_delete=models.CASCADE, blank=True, null=True)
+ connection_type = models.CharField(max_length=10, choices=ConnectionType.choices())
+
+ def clean(self):
+ super().clean()
+
+ if not self.mac_address_validation(self.mac_address):
+ raise ValidationError("Invalid MAC Address format")
+
+ @staticmethod
+ def mac_address_validation(mac_address: str) -> bool:
+ MAC_ADDRESS_PATTERN = r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})|([0-9a-fA-F]{4}\.[0-9a-fA-F]{4}\.[0-9a-fA-F]{4})$"
+ return re.match(MAC_ADDRESS_PATTERN, mac_address) is not None
+
+ class Meta:
+ abstract = True
+
+
+class ClientDevice(NetworkedDevice):
+ pass
+
+
+class NetworkDevice(NetworkedDevice):
+ device_type = models.CharField(max_length=20, choices=NetworkDeviceType.choices())
+
+
+class InfrastructureDevice(Device):
+ device_type = models.CharField(max_length=20, choices=InfrastructureDeviceType.choices())
diff --git a/network/models/rack.py b/network/models/rack.py
new file mode 100644
index 0000000..4b04baa
--- /dev/null
+++ b/network/models/rack.py
@@ -0,0 +1,68 @@
+from enum import Enum
+
+from django.db import models
+
+from common.utils.units import mm_to_inch
+from network.models import NetworkDevice
+
+RACK_UNIT_HEIGHT = 44.45 # 1U = 44.45mm
+
+
+class RackWidth(int, Enum):
+ WIDTH_10 = 10
+ WIDTH_19 = 19
+ WIDTH_23 = 23
+
+ @property
+ def width(self) -> float:
+ """Width of the Rack in Inches"""
+ return self.value
+
+ @classmethod
+ def choices(cls) -> list[tuple[int, str]]:
+ """Choices for the Rack Width"""
+ return [(width.value, width.name) for width in cls]
+
+
+class Rack(models.Model):
+ name = models.CharField(max_length=50)
+ width = models.PositiveIntegerField(choices=RackWidth.choices())
+ rack_units = models.FloatField()
+
+ @property
+ def height(self) -> float:
+ """Total Unit height of the Rack in mm"""
+ return round(self.rack_units * RACK_UNIT_HEIGHT)
+
+ @property
+ def height_inches(self) -> float:
+ """Height of the Rack Item in Inches"""
+ return round(mm_to_inch(self.height), 2)
+
+ @property
+ def remaining_units(self) -> int:
+ """Remaining Rack Units in the Rack"""
+ used_units = sum(item.rack_units for item in self.rack_items.all())
+ return self.rack_units - used_units
+
+
+class RackItem(models.Model):
+ name = models.CharField(max_length=50)
+ rack_units = models.FloatField()
+ rack = models.ForeignKey(Rack, on_delete=models.CASCADE, related_name="rack_items")
+ device = models.OneToOneField(NetworkDevice, on_delete=models.CASCADE, blank=True, null=True, related_name="rack_item")
+
+ @property
+ def height(self) -> float:
+ """Height of the Rack Item in mm"""
+ return round(self.height_units * RACK_UNIT_HEIGHT)
+
+ @property
+ def height_inches(self) -> float:
+ """Height of the Rack Item in Inches"""
+ return round(mm_to_inch(self.height), 2)
+
+ def save(self, *args, **kwargs):
+ if self.rack_units > self.rack.remaining_units:
+ raise ValueError(f"Not enough space in Rack {self.rack.name} for this RackItem {self.name}")
+ super().save(*args, **kwargs)
diff --git a/network/objects.py b/network/objects.py
new file mode 100644
index 0000000..0ca78ad
--- /dev/null
+++ b/network/objects.py
@@ -0,0 +1,36 @@
+from enum import Enum
+
+
+class ConnectionType(Enum):
+ ETHERNET = "ethernet"
+ WIFI = "wifi"
+
+ @classmethod
+ def choices(cls) -> list[tuple[str, str]]:
+ """Choices for the Connection Types"""
+ return [(connection.name, connection.value.capitalize()) for connection in cls]
+
+
+class NetworkDeviceType(Enum):
+ ROUTER = "router"
+ FIREWALL = "firewall"
+ SWITCH = "switch"
+ ACCESS_POINT = "access_point"
+ STORAGE = "storage"
+
+ @classmethod
+ def choices(cls) -> list[tuple[str, str]]:
+ """Choices for the Network Device Types"""
+ return [(device.name, device.value.capitalize()) for device in cls]
+
+
+class InfrastructureDeviceType(Enum):
+ POWER = "power"
+ PATCH_PANEL = "patch_panel"
+ BLANK = "blank"
+ CABLE_MANAGEMENT = "cable_management"
+
+ @classmethod
+ def choices(cls) -> list[tuple[str, str]]:
+ """Choices for the Infrastructure Device Types"""
+ return [(device.name, device.value.capitalize()) for device in cls]
diff --git a/network/templates/network/device/edit.html b/network/templates/network/device/client_edit.html
similarity index 86%
rename from network/templates/network/device/edit.html
rename to network/templates/network/device/client_edit.html
index 4e7b424..f082521 100644
--- a/network/templates/network/device/edit.html
+++ b/network/templates/network/device/client_edit.html
@@ -9,7 +9,7 @@
{% endblock %}
{% block form_action %}
-{% url 'device.edit' device.id %}
+{% url 'client_device.edit' device.id %}
{% endblock %}
{% block back_link %}
diff --git a/network/templates/network/device/create.html b/network/templates/network/device/create.html
index db263ad..de4ae08 100644
--- a/network/templates/network/device/create.html
+++ b/network/templates/network/device/create.html
@@ -1,5 +1,7 @@
{% extends "base/crud.html" %}
+{% load crispy_forms_tags %}
+
{% block title_content %}
Create Device
{% endblock %}
@@ -8,10 +10,46 @@
Create Device
{% endblock %}
-{% block form_action %}
-{% url 'device.create' %}
-{% endblock %}
-
{% block back_link %}
{% url 'device.index' %}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
+
+{% block additional_content %}
+
+Device Type:
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/network/templates/network/device/index.html b/network/templates/network/device/index.html
index 7f797fb..d8da001 100644
--- a/network/templates/network/device/index.html
+++ b/network/templates/network/device/index.html
@@ -20,11 +20,12 @@
VLAN |
Wifi Network |
Connection |
+ Device Type |
{% endblock %}
{% block table_body %}
-{% for device in devices %}
+{% for device in client_devices %}
{{ device.name }} |
{{ device.mac_address }} |
@@ -32,11 +33,30 @@
{{ device.vlan }} |
{{ device.wifi.ssid }} |
{{ device.connection_type }} |
+ Client |
- Edit
+ Edit
|
- Delete
+ Delete
+ |
+
+{% endfor %}
+{% for device in network_devices %}
+
+ {{ device.name }} |
+ {{ device.mac_address }} |
+ {{ device.ip_address }} |
+ {{ device.vlan }} |
+ {{ device.wifi.ssid }} |
+ {{ device.connection_type }} |
+ Network |
+ {{ device.device_type }} |
+
+ Edit
+ |
+
+ Delete
|
{% endfor %}
diff --git a/network/templates/network/device/network_edit.html b/network/templates/network/device/network_edit.html
new file mode 100644
index 0000000..0c68d94
--- /dev/null
+++ b/network/templates/network/device/network_edit.html
@@ -0,0 +1,17 @@
+{% extends "base/crud.html" %}
+
+{% block title_content %}
+Edit Device
+{% endblock %}
+
+{% block header_content %}
+Edit Device - {{ device.name }}
+{% endblock %}
+
+{% block form_action %}
+{% url 'network_device.edit' device.id %}
+{% endblock %}
+
+{% block back_link %}
+{% url 'device.index' %}
+{% endblock %}
\ No newline at end of file
diff --git a/network/templates/network/rack/create.html b/network/templates/network/rack/create.html
new file mode 100644
index 0000000..7d2b1cc
--- /dev/null
+++ b/network/templates/network/rack/create.html
@@ -0,0 +1,17 @@
+{% extends "base/crud.html" %}
+
+{% block title_content %}
+Create Rack
+{% endblock %}
+
+{% block header_content %}
+Create Rack
+{% endblock %}
+
+{% block form_action %}
+{% url 'rack.create' %}
+{% endblock %}
+
+{% block back_link %}
+{% url 'rack.index' %}
+{% endblock %}
\ No newline at end of file
diff --git a/network/templates/network/rack/edit.html b/network/templates/network/rack/edit.html
new file mode 100644
index 0000000..c856501
--- /dev/null
+++ b/network/templates/network/rack/edit.html
@@ -0,0 +1,17 @@
+{% extends "base/crud.html" %}
+
+{% block title_content %}
+Edit Rack
+{% endblock %}
+
+{% block header_content %}
+Edit Rack - {{ rack.name }}
+{% endblock %}
+
+{% block form_action %}
+{% url 'rack.edit' rack.id %}
+{% endblock %}
+
+{% block back_link %}
+{% url 'rack.index' %}
+{% endblock %}
\ No newline at end of file
diff --git a/network/templates/network/rack/index.html b/network/templates/network/rack/index.html
new file mode 100644
index 0000000..26e64eb
--- /dev/null
+++ b/network/templates/network/rack/index.html
@@ -0,0 +1,47 @@
+{% extends "base/index.html" %}
+
+{% block title_content %}
+Racks
+{% endblock %}
+
+{% block header_content %}
+Racks
+{% endblock %}
+
+{% block create_link %}
+{% url 'rack.create' %}
+{% endblock %}
+
+
+{% block table_head %}
+
+ Name |
+ Width (Inch) |
+ Height (Inch) |
+ Total Units |
+ Available Units |
+
+{% endblock %}
+
+{% block table_body %}
+{% for rack in racks %}
+
+ {{ rack.name }} |
+ {{ rack.width }} |
+ {{ rack.height_inches }} |
+ {{ rack.rack_units }} |
+ {{ rack.remaining_units }} |
+
+
+
+
+ |
+
+ Edit
+ |
+
+ Delete
+ |
+
+{% endfor %}
+{% endblock %}
\ No newline at end of file
diff --git a/network/templates/network/rack_item/create.html b/network/templates/network/rack_item/create.html
new file mode 100644
index 0000000..25be4c2
--- /dev/null
+++ b/network/templates/network/rack_item/create.html
@@ -0,0 +1,17 @@
+{% extends "base/crud.html" %}
+
+{% block title_content %}
+Create Rack Item
+{% endblock %}
+
+{% block header_content %}
+Create Rack Item
+{% endblock %}
+
+{% block form_action %}
+{% url 'rack_item.create' %}
+{% endblock %}
+
+{% block back_link %}
+{% url 'rack.index' %}
+{% endblock %}
\ No newline at end of file
diff --git a/network/templates/network/rack_item/edit.html b/network/templates/network/rack_item/edit.html
new file mode 100644
index 0000000..af736e9
--- /dev/null
+++ b/network/templates/network/rack_item/edit.html
@@ -0,0 +1,17 @@
+{% extends "base/crud.html" %}
+
+{% block title_content %}
+Edit Rack Item
+{% endblock %}
+
+{% block header_content %}
+Edit Rack Item - {{ rack_item.name }}
+{% endblock %}
+
+{% block form_action %}
+{% url 'rack_item.edit' rack_item.id %}
+{% endblock %}
+
+{% block back_link %}
+{% url 'rack.index' %}
+{% endblock %}
\ No newline at end of file
diff --git a/network/templates/network/rack_item/index.html b/network/templates/network/rack_item/index.html
new file mode 100644
index 0000000..d842dfa
--- /dev/null
+++ b/network/templates/network/rack_item/index.html
@@ -0,0 +1,35 @@
+{% extends "base/index.html" %}
+
+{% block title_content %}
+Racks Items
+{% endblock %}
+
+{% block header_content %}
+Rack Items : {{ rack.name }}
+{% endblock %}
+
+{% block create_link %}
+{% url 'rack_item.create' %}
+{% endblock %}
+
+{% block table_head %}
+
+ Name |
+ Rack Units |
+
+{% endblock %}
+
+{% block table_body %}
+{% for rack_item in rack_items %}
+
+ {{ rack_item.name }} |
+ {{ rack_item.rack_units }} |
+
+ Edit
+ |
+
+ Delete
+ |
+
+{% endfor %}
+{% endblock %}
diff --git a/network/tests.py b/network/tests.py
deleted file mode 100644
index 7ce503c..0000000
--- a/network/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/network/urls.py b/network/urls.py
index 28f8886..d27c9aa 100644
--- a/network/urls.py
+++ b/network/urls.py
@@ -1,19 +1,78 @@
-from django.urls import path
+from django.urls import include, path
from . import views
urlpatterns = [
path("", views.index.index, name="network_index"),
- path("vlan", views.vlan.index, name="vlan.index"),
- path("vlan/create", views.vlan.create, name="vlan.create"),
- path("vlan//edit", views.vlan.edit, name="vlan.edit"),
- path("vlan//delete", views.vlan.delete, name="vlan.delete"),
- path("wifi", views.wifi.index, name="wifi.index"),
- path("wifi/create", views.wifi.create, name="wifi.create"),
- path("wifi//edit", views.wifi.edit, name="wifi.edit"),
- path("wifi//delete", views.wifi.delete, name="wifi.delete"),
- path("device", views.device.index, name="device.index"),
- path("device/create", views.device.create, name="device.create"),
- path("device//edit", views.device.edit, name="device.edit"),
- path("device//delete", views.device.delete, name="device.delete"),
+ path(
+ "vlan/",
+ include(
+ [
+ path("", views.vlan.index, name="vlan.index"),
+ path("create", views.vlan.create, name="vlan.create"),
+ path("/edit", views.vlan.edit, name="vlan.edit"),
+ path("/delete", views.vlan.delete, name="vlan.delete"),
+ ]
+ ),
+ ),
+ path(
+ "wifi/",
+ include(
+ [
+ path("", views.wifi.index, name="wifi.index"),
+ path("create", views.wifi.create, name="wifi.create"),
+ path("/edit", views.wifi.edit, name="wifi.edit"),
+ path("/delete", views.wifi.delete, name="wifi.delete"),
+ ]
+ ),
+ ),
+ path(
+ "device/",
+ include(
+ [
+ path("", views.device.index, name="device.index"),
+ path("create", views.device.create, name="device.create"),
+ path(
+ "client/",
+ include(
+ [
+ path("/edit", views.device.edit_client, name="client_device.edit"),
+ path("/delete", views.device.delete_client, name="client_device.delete"),
+ ]
+ ),
+ ),
+ path(
+ "network/",
+ include(
+ [
+ path("/edit", views.device.edit_network, name="network_device.edit"),
+ path("/delete", views.device.delete_network, name="network_device.delete"),
+ ]
+ ),
+ ),
+ ]
+ ),
+ ),
+ path(
+ "rack/",
+ include(
+ [
+ path("", views.rack.index, name="rack.index"),
+ path("create", views.rack.create_rack, name="rack.create"),
+ path("/edit", views.rack.edit_rack, name="rack.edit"),
+ path("/delete", views.rack.delete_rack, name="rack.delete"),
+ path("/", views.rack.rack_index, name="rack.view"),
+ ]
+ ),
+ ),
+ path(
+ "rack-item/",
+ include(
+ [
+ path("create", views.rack.create_rack_item, name="rack_item.create"),
+ path("/edit", views.rack.edit_rack_item, name="rack_item.edit"),
+ path("/delete", views.rack.delete_rack_item, name="rack_item.delete"),
+ ]
+ ),
+ ),
]
diff --git a/network/views/__init__.py b/network/views/__init__.py
index 2c4b302..f98a531 100644
--- a/network/views/__init__.py
+++ b/network/views/__init__.py
@@ -1 +1 @@
-from . import device, index, vlan, wifi
+from . import device, index, rack, vlan, wifi
diff --git a/network/views/device.py b/network/views/device.py
index 6d28309..0e62b2a 100644
--- a/network/views/device.py
+++ b/network/views/device.py
@@ -1,12 +1,12 @@
from django.shortcuts import get_object_or_404, redirect, render
-from ..forms import ClientDeviceForm
-from ..models import ClientDevice, VLAN, WifiNetwork
-
+from ..forms.devices import ClientDeviceForm, NetworkDeviceForm
+from ..models import ClientDevice, NetworkDevice, VLAN, WifiNetwork
def index(request):
- devices = ClientDevice.objects.all()
- return render(request, "network/device/index.html", {"devices": devices})
+ client_devices = ClientDevice.objects.all()
+ network_devices = NetworkDevice.objects.all()
+ return render(request, "network/device/index.html", {"client_devices": client_devices, "network_devices": network_devices})
def create(request):
@@ -14,17 +14,29 @@ def create(request):
wifi_options = [(wifi.id, wifi.ssid) for wifi in WifiNetwork.objects.all()]
if request.method == "POST":
- form = ClientDeviceForm(request.POST, vlan_options=vlan_options, wifi_options=wifi_options)
- if form.is_valid():
- form.save()
- return redirect("device.index")
+ if "client" in request.POST:
+ client_form = ClientDeviceForm(request.POST, vlan_options=vlan_options, wifi_options=wifi_options)
+ if client_form.is_valid():
+ client_form.save()
+ return redirect("device.index")
+ elif "network" in request.POST:
+ network_form = NetworkDeviceForm(request.POST, vlan_options=vlan_options, wifi_options=wifi_options)
+ if network_form.is_valid():
+ network_form.save()
+ return redirect("device.index")
else:
- form = ClientDeviceForm(vlan_options=vlan_options, wifi_options=wifi_options)
+ client_form = ClientDeviceForm(vlan_options=vlan_options, wifi_options=wifi_options)
+ network_form = NetworkDeviceForm(vlan_options=vlan_options, wifi_options=wifi_options)
+
+ if not client_form:
+ client_form = ClientDeviceForm(vlan_options=vlan_options, wifi_options=wifi_options)
+ if not network_form:
+ network_form = NetworkDeviceForm(vlan_options=vlan_options, wifi_options=wifi_options)
- return render(request, "network/device/create.html", {"form": form})
+ return render(request, "network/device/create.html", {"client_form": client_form, "network_form": network_form, "show_form": False})
-def edit(request, id: int):
+def edit_client(request, id: int):
device = get_object_or_404(ClientDevice, id=id)
vlan_options = [(vlan.vlan_id, f"{vlan.vlan_id} - {vlan.name}") for vlan in VLAN.objects.all()]
@@ -38,10 +50,33 @@ def edit(request, id: int):
else:
form = ClientDeviceForm(instance=device, vlan_options=vlan_options, wifi_options=wifi_options)
- return render(request, "network/device/edit.html", {"form": form, "device": device})
+ return render(request, "network/device/client_edit.html", {"form": form, "device": device})
+
+def edit_network(request, id: int):
+ device = get_object_or_404(NetworkDevice, id=id)
-def delete(request, id: int):
+ vlan_options = [(vlan.vlan_id, f"{vlan.vlan_id} - {vlan.name}") for vlan in VLAN.objects.all()]
+ wifi_options = [(wifi.id, wifi.ssid) for wifi in WifiNetwork.objects.all()]
+
+ if request.method == "POST":
+ form = NetworkDeviceForm(request.POST, instance=device, vlan_options=vlan_options, wifi_options=wifi_options)
+ if form.is_valid():
+ form.save()
+ return redirect("device.index")
+ else:
+ form = NetworkDeviceForm(instance=device, vlan_options=vlan_options, wifi_options=wifi_options)
+
+ return render(request, "network/device/network_edit.html", {"form": form, "device": device})
+
+
+def delete_client(request, id: int):
device = get_object_or_404(ClientDevice, id=id)
device.delete()
return redirect("device.index")
+
+
+def delete_network(request, id: int):
+ device = get_object_or_404(NetworkDevice, id=id)
+ device.delete()
+ return redirect("device.index")
diff --git a/network/views/rack.py b/network/views/rack.py
new file mode 100644
index 0000000..83babb3
--- /dev/null
+++ b/network/views/rack.py
@@ -0,0 +1,84 @@
+from django.shortcuts import get_object_or_404, redirect, render
+
+from ..forms.rack import RackForm, RackItemForm
+from ..models import NetworkDevice, Rack, RackItem
+
+def index(request):
+ racks = Rack.objects.all()
+ return render(request, "network/rack/index.html", {"racks": racks})
+
+
+def rack_index(request, rack_id):
+ rack = get_object_or_404(Rack, id=rack_id)
+ rack_items = RackItem.objects.filter(rack=rack)
+ return render(request, "network/rack_item/index.html", {"rack": rack, "rack_items": rack_items})
+
+
+def create_rack(request):
+ if request.method == "POST":
+ form = RackForm(request.POST)
+ if form.is_valid():
+ form.save()
+ return redirect("rack.index")
+ else:
+ form = RackForm()
+
+ return render(request, "network/rack/create.html", {"form": form})
+
+
+def create_rack_item(request):
+ rack_options = [(rack.id, rack.name) for rack in Rack.objects.all()]
+ device_options = [(device.id, device.name) for device in NetworkDevice.objects.all()]
+
+ if request.method == "POST":
+ form = RackItemForm(request.POST, rack_options=rack_options, device_options=device_options)
+ if form.is_valid():
+ form.save()
+ return redirect("rack_item.index")
+ else:
+ form = RackItemForm(rack_options=rack_options, device_options=device_options)
+
+ return render(request, "network/rack_item/create.html", {"form": form})
+
+
+def edit_rack(request, rack_id: int):
+ rack = get_object_or_404(Rack, id=rack_id)
+
+ if request.method == "POST":
+ form = RackForm(request.POST, instance=rack)
+ if form.is_valid():
+ form.save()
+ return redirect("rack.index")
+ else:
+ form = RackForm(instance=rack)
+
+ return render(request, "network/rack/edit.html", {"form": form, "rack": rack})
+
+
+def edit_rack_item(request, rack_item_id: int):
+ rack_options = [(rack.id, rack.name) for rack in Rack.objects.all()]
+ device_options = [(device.id, device.name) for device in NetworkDevice.objects.all()]
+
+ rack_item = get_object_or_404(RackItem, id=rack_item_id)
+
+ if request.method == "POST":
+ form = RackItemForm(request.POST, instance=rack_item, rack_options=rack_options, device_options=device_options)
+ if form.is_valid():
+ form.save()
+ return redirect("rack_item.index")
+ else:
+ form = RackItemForm(instance=rack_item, rack_options=rack_options, device_options=device_options)
+
+ return render(request, "network/rack_item/edit.html", {"form": form, "rack_item": rack_item})
+
+
+def delete_rack(request, rack_id: int):
+ rack = get_object_or_404(Rack, id=rack_id)
+ rack.delete()
+ return redirect("rack.index")
+
+
+def delete_rack_item(request, rack_item_id: int):
+ rack_item = get_object_or_404(RackItem, id=rack_item_id)
+ rack_item.delete()
+ return redirect("rack_item.index")
diff --git a/network/views/vlan.py b/network/views/vlan.py
index b4e9222..24928ad 100644
--- a/network/views/vlan.py
+++ b/network/views/vlan.py
@@ -1,9 +1,8 @@
from django.shortcuts import get_object_or_404, redirect, render
-from ..forms import VLANForm
+from ..forms.networking import VLANForm
from ..models import VLAN
-
def index(request):
vlans = VLAN.objects.all()
return render(request, "network/vlan/index.html", {"vlans": vlans})
diff --git a/network/views/wifi.py b/network/views/wifi.py
index 1cfea37..679eaa9 100644
--- a/network/views/wifi.py
+++ b/network/views/wifi.py
@@ -1,9 +1,8 @@
from django.shortcuts import get_object_or_404, redirect, render
-from ..forms import WifiForm
+from ..forms.networking import WifiForm
from ..models import WifiNetwork
-
def index(request):
wifis = WifiNetwork.objects.all()
return render(request, "network/wifi/index.html", {"wifis": wifis})