Не сохранять, если одно из 2 полей не уникально (Обновленный вопрос)
У меня следующие коды
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})
Как вы можете видеть, в моем models.py в классе device(hostname- unique=true) и class devicedetail(mgt_ip_addr - unique = true). Поэтому, когда пользователь вводит на странице одно и то же существующее имя хоста или mgt_ip_addr, оно должно быть отклонено и не сохранено в базе данных.
< < < <Выдается предупреждение о том, что mgt_ip_addr уже существует. Но форма все равно сохраняется для таблицы Device. Таким образом, имя хоста ключа Test1, введенного пользователем C, сохраняется в базе данных. Но другие таблицы не сохраняются (нежелательно)
Желаемый результат : Пользователь C вводит test1 для имени хоста и 1.1.1.1 для mgt_ip_addr
Предупреждение о необходимости отображения mgt_ip_addr и отклонение формы для пользователя C.
Может ли кто-нибудь посоветовать мне, что я делаю неправильно?
Хочу поделиться ответом. Невозможно иметь уникальные поля в отдельных таблицах в рамках одной формы. Я не знаю, может я не прав. Но у меня это работает, так что да.