I have the following codes
models.py:
class Device(models.Model):
hostname = models.CharField(max_length=50, unique=True)
ipaddr = models.GenericIPAddressField(protocol='ipv4', default='0.0.0.0')
date_added = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.hostname
class DeviceDetail(models.Model):
SUBNET_CHOICES = (
('16','16'),
('17', '17'),
('18','18'),
('19','19'),
('20','20'),
('21', '21'),
('22', '22'),
('23', '23'),
('24', '24'),
('25', '25'),
('26', '26'),
('27', '27'),
('28', '28'),
('29', '29'),
('30', '30'),
)
DEV_MODS =(
('Catalyst 9606R', 'Catalyst 9606R'),
('C9300L-48T-4X', 'C9300L-48T-4X')
)
hostname = models.CharField(max_length=50)
mgt_interface = models.CharField(max_length=50)
mgt_ip_addr = models.GenericIPAddressField(protocol='ipv4', unique=True)
subnetmask = models.CharField(max_length=2, choices = SUBNET_CHOICES)
ssh_id = models.CharField(max_length=50)
ssh_pwd = models.CharField(max_length=50)
enable_secret = models.CharField(max_length=50)
dev_mod=models.CharField(max_length=50, choices = DEV_MODS) ##device_model replacement
DD2DKEY = models.ForeignKey(Device, on_delete=models.CASCADE) ##The key to link up the tables
def __str__(self):
return self.hostname
class DeviceInterface(models.Model):
MODULE_ID_CHOICES = (
('TenGigabitEthernet','TenGigabitEthernet'),
('FortyGigabitEthernet','FortyGigabitEthernet'),
('GigabitEthernet','GigabitEthernet'),
('Ethernet','Ethernet'),
)
moduletype = models.CharField(max_length = 50,choices = MODULE_ID_CHOICES)
firstportid = models.CharField(max_length=50)
lastportid = models.CharField(max_length=50)
I2DKEY = models.ForeignKey(Device, on_delete=models.CASCADE) ##The key to link up the tables
def __str__(self):
return self.moduletype
forms.py:
class DeviceForm(ModelForm):
class Meta:
model= Device
fields= ['hostname']
labels = {
"hostname": "Hostname",
}
class DeviceDetailForm(ModelForm):
class Meta:
model= DeviceDetail
fields= ['hostname', 'mgt_interface', 'mgt_ip_addr', 'subnetmask', 'ssh_id', 'ssh_pwd', 'enable_secret', 'dev_mod']
labels = {
"mgt_ip_addr": "Management IP Address",
}
widgets = {
'enable_secret': forms.PasswordInput(),
'ssh_pwd': forms.PasswordInput()
}
def clean_hostname(self):
hostname = self.cleaned_data['hostname']
if len(hostname) < 8:
raise forms.ValidationError(f'Hostname needs to be more than 8 character long, {hostname}')
return hostname
class DeviceInterfaceForm(ModelForm):
class Meta:
model= DeviceInterface
fields= ['moduletype', 'firstportid', 'lastportid']
labels = {
"moduletype":"Module Type",
"firstportid": "First Port ID",
"lastportid": "Last Port ID"
}
widgets = {
'firstportid':forms.TextInput(attrs={
'placeholder': 'e.g. TenGigabitEthernet1/0/1',
'class':'form-control',
'onchange':'portidChange(this.value)'
}),
'lastportid':forms.TextInput(attrs={
'placeholder': 'e.g. TenGigabitEthernet1/0/48',
'class': 'form-control',
'onchange':'portidChange(this.value)'
})
}
views.py:
def device_add(request):
if request.method == "POST":
device_frm = DeviceForm(request.POST) ##Part A1
dd_form = DeviceDetailForm(request.POST)
di_formset = modelformset_factory(DeviceInterface, fields=('moduletype', 'firstportid', 'lastportid'), extra=1,max_num=3)
di_form=di_formset(request.POST)
if device_frm.is_valid():
# Create and save the device
# new_device here is the newly created Device object
new_device = device_frm.save()
if dd_form.is_valid():
# Create an unsaved instance of device detail
deviceD = dd_form.save(commit=False)
# Set the device we just created above as this device detail's device
deviceD.DD2DKEY = new_device
# If you did not render the hostname for the device detail, set it from the value of new device
deviceD.hostname = new_device.hostname
deviceD.save()
if di_form.is_valid():
deviceI=di_form.save(commit=False)
for instances in deviceI:
instances.I2DKEY=new_device
instances.save()
return render(request, 'interface/device_added.html',{'devices':Device.objects.all()})
return render(request,'interface/device_add.html',{'form':device_frm, 'dd_form': dd_form, 'di_form':di_form})
return render(request,'interface/device_add.html',{'form':device_frm, 'dd_form': dd_form, 'di_form':di_form})
else:
device_frm = DeviceForm()
dd_form = DeviceDetailForm()
di_formset = modelformset_factory(DeviceInterface, fields=('moduletype', 'firstportid', 'lastportid'),extra=1, max_num=3)
di_form=di_formset(queryset = DeviceInterface.objects.none())
return render(request,'interface/device_add.html',{'form':device_frm, 'dd_form': dd_form, 'di_form':di_form})
As u can see, in my models.py under class device(hostname- unique=true) and class devicedetail(mgt_ip_addr - unique = true). So whenever user type the same existing hostname or mgt_ip_addr on the page, it should be rejected and not saved in database.
Here is the scenario:
- User A keys in Testing for hostname and 1.1.1.1 for mgt_ip_addr.
- User B keys in Testing for hostname and 1.1.1.1 for mgt_ip_addr.
- User C: keys in Testing1 for hostname and 1.1.1.1 for mgt_ip_addr
- User D: keys in Testing1 for hostname and 1.1.1.2 for mgt_ip_addr
Results:
-
Form get saved as User A is the first user to key in the following hostname and mgt_ip_addr (Worked as intended)
-
Form is rejected for User B as it has identical hostname and identical mgt_ip_addr as User A and does not get saved. (Worked as intended)
-
Warning is display saying mgt_ip_addr exist already as User A has this mgt_ip_addr. But the form still save the part for 1st table (Device) before rejecting the other fields (Not working as intended)
-
Warning displayed for hostname existing as User C has this hostname. (Not intended to save User C due to scenario 3). So the forms get rejected (Working as intended)
Desired outcome for scenario 3 :
Warning to display that mgt_ip_addr already exist so the form get rejected even though the hostname is different from any existing one
The codes seems to work as intended but at the very backend it got haywire which i dont know why. Can someone suggest what i can do to fix this issue?