Interface VLANs Not Updating Properly #7809

Closed
opened 2025-12-29 20:28:28 +01:00 by adam · 4 comments
Owner

Originally created by @adparis99 on GitHub (Mar 29, 2023).

Originally assigned to: @DanSheps on GitHub.

NetBox version

v3.4.7

Python version

3.10

Steps to Reproduce

  1. Select multiple device interfaces (that already have mode configured as tagged, an assigned untagged VLAN, and exactly one assigned tagged VLAN) and initiate a bulk edit
  2. Change the untagged VLAN
  3. Change the tagged VLAN
  4. Apply

Expected Behavior

Both the untagged and tagged VLAN of the interfaces are updated.

Observed Behavior

The interfaces are only updated with the supplied tagged VLAN; the untagged VLAN remains unchanged.

Before:
image

Attempted Changes:
image

After:
image

Originally created by @adparis99 on GitHub (Mar 29, 2023). Originally assigned to: @DanSheps on GitHub. ### NetBox version v3.4.7 ### Python version 3.10 ### Steps to Reproduce 1. Select multiple device interfaces (that already have mode configured as tagged, an assigned untagged VLAN, and exactly one assigned tagged VLAN) and initiate a bulk edit 2. Change the untagged VLAN 3. Change the tagged VLAN 4. Apply ### Expected Behavior Both the untagged and tagged VLAN of the interfaces are updated. ### Observed Behavior The interfaces are only updated with the supplied tagged VLAN; the untagged VLAN remains unchanged. Before: ![image](https://user-images.githubusercontent.com/16410007/228598503-0527952d-6732-4e4a-a1c8-936283e01bc4.png) Attempted Changes: ![image](https://user-images.githubusercontent.com/16410007/228598737-554e3ca4-45f5-452d-ac39-748288d12cfa.png) After: ![image](https://user-images.githubusercontent.com/16410007/228598855-f353df20-e754-43f5-a84d-51f920f15c60.png)
adam added the type: bugstatus: accepted labels 2025-12-29 20:28:28 +01:00
adam closed this issue 2025-12-29 20:28:28 +01:00
Author
Owner

@stuntguy3000 commented on GitHub (Apr 3, 2023):

After a lot of trial and error, I am fairly confident I am able to accurately describe the root cause of the bug.

Note that add(), create(), remove(), clear(), and set() all apply database changes immediately for all types of related fields. In other words, there is no need to call save() on either end of the relationship.
https://docs.djangoproject.com/en/4.1/ref/models/relations/

Essentially, the method of updating ManyToMany Fields causes a database update. Alongside this, the object instance is refreshed as well with data from the database - causing the changes not committed to the database to be lost (e.g. untagged VLANs!).

image
Untagged VLANs are updated on line 532
Tagged VLANs are updated on line 529

I'll leave it up to contributors who actually have experience with Django on how best to address this (committing the object change after every field change or moving to a different approach to update the tagged VLANs without a database call).

@stuntguy3000 commented on GitHub (Apr 3, 2023): After _a lot_ of trial and error, I am fairly confident I am able to accurately describe the root cause of the bug. > Note that add(), create(), remove(), clear(), and set() all apply database changes immediately for all types of related fields. In other words, there is no need to call save() on either end of the relationship. [https://docs.djangoproject.com/en/4.1/ref/models/relations/](https://docs.djangoproject.com/en/4.1/ref/models/relations/) Essentially, the method of updating ManyToMany Fields causes a database update. Alongside this, the object instance is refreshed as well with data from the database - **causing the changes not committed to the database to be lost** (e.g. untagged VLANs!). ![image](https://user-images.githubusercontent.com/1522389/229419389-39830f66-b4ca-4d1e-b9f1-f220edde2729.png) Untagged VLANs are updated on line 532 Tagged VLANs are updated on line 529 I'll leave it up to contributors who actually have experience with Django on how best to address this (committing the object change after every field change or moving to a different approach to update the tagged VLANs without a database call).
Author
Owner

@adparis99 commented on GitHub (Apr 3, 2023):

Thanks for looking into this! When I first noticed it I thought I was going crazy.

I'll leave it up to contributors who actually have experience with Django...

As someone who is not a contributor nor experienced with Django, I was wondering if I can pick your brain a bit about your hypothesis.

If the database update caused by set() on line 529 is causing uncommitted changes to be lost, why do custom fields still update properly (since they, like untagged VLANs, are updated after tagged VLANs)? Does it have to do how custom fields are handled in comparison to standard fields?

Also, if the problem is in fact caused by ManytoMany fields updating prior to normal fields, could those two elif statements simply be swapped so that ManyToMany fields are updated last, thus negating the issue? Truly just asking out of curiosity. Thanks again for your help.

@adparis99 commented on GitHub (Apr 3, 2023): Thanks for looking into this! When I first noticed it I thought I was going crazy. > I'll leave it up to contributors who actually have experience with Django... As someone who is not a contributor nor experienced with Django, I was wondering if I can pick your brain a bit about your hypothesis. If the database update caused by set() on line 529 is causing uncommitted changes to be lost, why do custom fields still update properly (since they, like untagged VLANs, are updated after tagged VLANs)? Does it have to do how custom fields are handled in comparison to standard fields? Also, if the problem is in fact caused by ManytoMany fields updating prior to normal fields, could those two elif statements simply be swapped so that ManyToMany fields are updated last, thus negating the issue? Truly just asking out of curiosity. Thanks again for your help.
Author
Owner

@DanSheps commented on GitHub (Apr 3, 2023):

Confirmed that this is indeed what is happening.

I think it might be better to build a list of rels like we do custom_fields and handle them after the main iteration happens.

@DanSheps commented on GitHub (Apr 3, 2023): Confirmed that this is indeed what is happening. I think it might be better to build a list of rels like we do custom_fields and handle them after the main iteration happens.
Author
Owner

@stuntguy3000 commented on GitHub (Apr 3, 2023):

If the database update caused by set() on line 529 is causing uncommitted changes to be lost, why do custom fields still update properly (since they, like untagged VLANs, are updated after tagged VLANs)? Does it have to do how custom fields are handled in comparison to standard fields?

Put simply, further down in the code the object (only a few lines more) is saved - which causes it to be updated.

Also, if the problem is in fact caused by ManytoMany fields updating prior to normal fields, could those two elif statements simply be swapped so that ManyToMany fields are updated last, thus negating the issue? Truly just asking out of curiosity. Thanks again for your help.

It's not viable as these elif statements are executed in a loop through of each form object, so order of the if statements don't matter in this instance.

Thanks @DanSheps, I agree with your idea

@stuntguy3000 commented on GitHub (Apr 3, 2023): > If the database update caused by set() on line 529 is causing uncommitted changes to be lost, why do custom fields still update properly (since they, like untagged VLANs, are updated after tagged VLANs)? Does it have to do how custom fields are handled in comparison to standard fields? Put simply, further down in the code the object (only a few lines more) is saved - which causes it to be updated. > Also, if the problem is in fact caused by ManytoMany fields updating prior to normal fields, could those two elif statements simply be swapped so that ManyToMany fields are updated last, thus negating the issue? Truly just asking out of curiosity. Thanks again for your help. It's not viable as these elif statements are executed in a loop through of each form object, so order of the if statements don't matter in this instance. Thanks @DanSheps, I agree with your idea
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#7809