1
0
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:
Jeremy Stretch
2020-01-30 15:12:10 -05:00
parent b9765b857d
commit 1a25f5a7f2
3 changed files with 22 additions and 9 deletions

View File

@ -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

View File

@ -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)

View File

@ -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()