mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixes #4030: Fix exception when bulk editing interfaces (revised)
This commit is contained in:
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
## Bug Fixes
|
## Bug Fixes
|
||||||
|
|
||||||
|
* [#4030](https://github.com/netbox-community/netbox/issues/4030) - Fix exception when bulk editing interfaces (revised)
|
||||||
* [#4043](https://github.com/netbox-community/netbox/issues/4043) - Fix toggling of required fields in custom scripts
|
* [#4043](https://github.com/netbox-community/netbox/issues/4043) - Fix toggling of required fields in custom scripts
|
||||||
* [#4049](https://github.com/netbox-community/netbox/issues/4049) - Restore missing `tags` field in IPAM service serializer
|
* [#4049](https://github.com/netbox-community/netbox/issues/4049) - Restore missing `tags` field in IPAM service serializer
|
||||||
* [#4052](https://github.com/netbox-community/netbox/issues/4052) - Fix error when bulk importing interfaces to virtual machines
|
* [#4052](https://github.com/netbox-community/netbox/issues/4052) - Fix error when bulk importing interfaces to virtual machines
|
||||||
|
@ -676,7 +676,7 @@ class Interface(CableTermination, ComponentModel):
|
|||||||
self.untagged_vlan = None
|
self.untagged_vlan = None
|
||||||
|
|
||||||
# Only "tagged" interfaces may have tagged VLANs assigned. ("tagged all" implies all VLANs are assigned.)
|
# Only "tagged" interfaces may have tagged VLANs assigned. ("tagged all" implies all VLANs are assigned.)
|
||||||
if self.pk and self.mode is not InterfaceModeChoices.MODE_TAGGED:
|
if self.pk and self.mode != InterfaceModeChoices.MODE_TAGGED:
|
||||||
self.tagged_vlans.clear()
|
self.tagged_vlans.clear()
|
||||||
|
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
@ -6,7 +6,7 @@ from django.contrib import messages
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import transaction, IntegrityError
|
from django.db import transaction, IntegrityError
|
||||||
from django.db.models import Count, ProtectedError
|
from django.db.models import Count, ManyToManyField, ProtectedError
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.forms import CharField, Form, ModelMultipleChoiceField, MultipleHiddenInput, Textarea
|
from django.forms import CharField, Form, ModelMultipleChoiceField, MultipleHiddenInput, Textarea
|
||||||
from django.http import HttpResponse, HttpResponseServerError
|
from django.http import HttpResponse, HttpResponseServerError
|
||||||
@ -650,7 +650,9 @@ class BulkEditView(GetReturnURLMixin, View):
|
|||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
|
||||||
custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else []
|
custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else []
|
||||||
standard_fields = [field for field in form.fields if field not in custom_fields and field != 'pk']
|
standard_fields = [
|
||||||
|
field for field in form.fields if field not in custom_fields + ['pk', 'add_tags', 'remove_tags']
|
||||||
|
]
|
||||||
nullified_fields = request.POST.getlist('_nullify')
|
nullified_fields = request.POST.getlist('_nullify')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -662,14 +664,24 @@ class BulkEditView(GetReturnURLMixin, View):
|
|||||||
|
|
||||||
# Update standard fields. If a field is listed in _nullify, delete its value.
|
# Update standard fields. If a field is listed in _nullify, delete its value.
|
||||||
for name in standard_fields:
|
for name in standard_fields:
|
||||||
if name in form.nullable_fields and name in nullified_fields and isinstance(form.cleaned_data[name], QuerySet):
|
|
||||||
|
model_field = model._meta.get_field(name)
|
||||||
|
|
||||||
|
# Handle nullification
|
||||||
|
if name in form.nullable_fields and name in nullified_fields:
|
||||||
|
if isinstance(model_field, ManyToManyField):
|
||||||
getattr(obj, name).set([])
|
getattr(obj, name).set([])
|
||||||
elif name in form.nullable_fields and name in nullified_fields:
|
else:
|
||||||
setattr(obj, name, '' if isinstance(form.fields[name], CharField) else None)
|
setattr(obj, name, None if model_field.null else '')
|
||||||
elif isinstance(form.cleaned_data[name], QuerySet) and form.cleaned_data[name]:
|
|
||||||
|
# ManyToManyFields
|
||||||
|
elif isinstance(model_field, ManyToManyField):
|
||||||
getattr(obj, name).set(form.cleaned_data[name])
|
getattr(obj, name).set(form.cleaned_data[name])
|
||||||
elif form.cleaned_data[name] not in (None, '') and not isinstance(form.cleaned_data[name], QuerySet):
|
|
||||||
|
# Normal fields
|
||||||
|
elif form.cleaned_data[name] not in (None, ''):
|
||||||
setattr(obj, name, form.cleaned_data[name])
|
setattr(obj, name, form.cleaned_data[name])
|
||||||
|
|
||||||
obj.full_clean()
|
obj.full_clean()
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user