Utility function get_field_value returns last value when used on a multi-value field #10376

Closed
opened 2025-12-29 21:30:37 +01:00 by adam · 6 comments
Owner

Originally created by @DanSheps on GitHub (Oct 17, 2024).

Deployment Type

Self-hosted

Triage priority

I volunteer to perform this work (if approved)

NetBox Version

v4.1.4

Python Version

3.10

Steps to Reproduce

  1. Utilize get_field_value on a form field that may produce a single value or multiple values (Ex: tagged_vlans)

Expected Behavior

get_field_value to return multiple values

Observed Behavior

get_field_valueu returns a single value

Originally created by @DanSheps on GitHub (Oct 17, 2024). ### Deployment Type Self-hosted ### Triage priority I volunteer to perform this work (if approved) ### NetBox Version v4.1.4 ### Python Version 3.10 ### Steps to Reproduce 1. Utilize get_field_value on a form field that may produce a single value or multiple values (Ex: `tagged_vlans`) ### Expected Behavior get_field_value to return multiple values ### Observed Behavior get_field_valueu returns a single value
adam added the netbox label 2025-12-29 21:30:37 +01:00
adam closed this issue 2025-12-29 21:30:37 +01:00
Author
Owner

@DanSheps commented on GitHub (Oct 17, 2024):

This is expected (but annoying) behaviour as per: https://code.djangoproject.com/ticket/1130

Two options are possible:

  1. Rewrite get_field_value to dynamically determine if the field is capable of returning multiple values
  2. Create a new get_field_values to call getlist() instead of get()
@DanSheps commented on GitHub (Oct 17, 2024): This is expected (but annoying) behaviour as per: https://code.djangoproject.com/ticket/1130 Two options are possible: 1. Rewrite `get_field_value` to dynamically determine if the field is capable of returning multiple values 2. Create a new `get_field_values` to call getlist() instead of get()
Author
Owner

@DanSheps commented on GitHub (Oct 17, 2024):

Proposed rewrite:

def get_field_value(form, field_name):
    """
    Return the current bound or initial value associated with a form field, prior to calling
    clean() for the form.
    """
    field = form.fields[field_name]
    
    if form.is_bound:
        # Get list or get single value
        if isinstance(field, MultipleChoiceField):
            data = form.data.getlist(field_name)
        else:
            data = form.data.get(field_name)
        
        if hasattr(field, 'valid_value') and field.valid_value(data):
            return data

    return form.get_initial_for_field(field, field_name)
@DanSheps commented on GitHub (Oct 17, 2024): Proposed rewrite: ``` def get_field_value(form, field_name): """ Return the current bound or initial value associated with a form field, prior to calling clean() for the form. """ field = form.fields[field_name] if form.is_bound: # Get list or get single value if isinstance(field, MultipleChoiceField): data = form.data.getlist(field_name) else: data = form.data.get(field_name) if hasattr(field, 'valid_value') and field.valid_value(data): return data return form.get_initial_for_field(field, field_name) ```
Author
Owner

@jeremystretch commented on GitHub (Apr 10, 2025):

@DanSheps to submit a PR per maintainers meeting

@jeremystretch commented on GitHub (Apr 10, 2025): @DanSheps to submit a PR per maintainers meeting
Author
Owner

@jeremystretch commented on GitHub (Apr 28, 2025):

@DanSheps could you please rewrite the original issue to include reproduction steps? I'm not able to reproduce this:

>>> from django.http import QueryDict
>>> from utilities.forms import get_field_value
>>> from dcim.forms import InterfaceForm
>>> 
>>> qd = QueryDict("mode=tagged&tagged_vlans=2&tagged_vlans=27")
>>> f = InterfaceForm(initial=qd)
>>> get_field_value(f, 'tagged_vlans')
['2', '27']
@jeremystretch commented on GitHub (Apr 28, 2025): @DanSheps could you please rewrite the original issue to include reproduction steps? I'm not able to reproduce this: ```python >>> from django.http import QueryDict >>> from utilities.forms import get_field_value >>> from dcim.forms import InterfaceForm >>> >>> qd = QueryDict("mode=tagged&tagged_vlans=2&tagged_vlans=27") >>> f = InterfaceForm(initial=qd) >>> get_field_value(f, 'tagged_vlans') ['2', '27'] ```
Author
Owner

@DanSheps commented on GitHub (May 15, 2025):

After re-reviewing the code, I realised I made an error before trying to fix this:

On March 31st, when fixing another issue, the code around this function changed from:

    if form.is_bound and (data := form.data.get(field_name)):
        if hasattr(field, 'valid_value') and field.valid_value(data):
            return data

to

    if form.is_bound and field_name in form.data:
        if (value := form.data[field_name]) is None:
            return
        if hasattr(field, 'valid_value') and field.valid_value(value):
            return value

This slight change in code seems to have resolved the issue fully as we are no longer using .get() to retrieve the field value.

@DanSheps commented on GitHub (May 15, 2025): After re-reviewing the code, I realised I made an error before trying to fix this: On March 31st, when fixing another issue, the code around this function changed from: ```python if form.is_bound and (data := form.data.get(field_name)): if hasattr(field, 'valid_value') and field.valid_value(data): return data ``` to ```python if form.is_bound and field_name in form.data: if (value := form.data[field_name]) is None: return if hasattr(field, 'valid_value') and field.valid_value(value): return value ``` This slight change in code seems to have resolved the issue fully as we are no longer using `.get()` to retrieve the field value.
Author
Owner

@DanSheps commented on GitHub (May 15, 2025):

Fixed by: https://github.com/netbox-community/netbox/issues/19023

@DanSheps commented on GitHub (May 15, 2025): Fixed by: https://github.com/netbox-community/netbox/issues/19023
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#10376