Batch editing 'date' type 'custom field' for multiple devices failed after upgrading to 3.4.x #7447

Closed
opened 2025-12-29 20:23:34 +01:00 by adam · 2 comments
Owner

Originally created by @wiyin on GitHub (Jan 4, 2023).

Originally assigned to: @jeremystretch on GitHub.

NetBox version

v3.4.2

Python version

3.8

Steps to Reproduce

  1. Add a custom field with the name testdate to the Circuit model with the type Date
  2. Add a circuit testcircuit
  3. Mark testcircuit in the circuit list and press Edit Selected

Expected Behavior

changes applied successfully

Observed Behavior

following error message

<class 'TypeError'>

fromisoformat: argument must be str

Python version: 3.8.10
NetBox version: 3.4.2
Originally created by @wiyin on GitHub (Jan 4, 2023). Originally assigned to: @jeremystretch on GitHub. ### NetBox version v3.4.2 ### Python version 3.8 ### Steps to Reproduce 1. Add a custom field with the name `testdate` to the `Circuit` model with the type `Date` 2. Add a circuit `testcircuit` 3. Mark `testcircuit` in the circuit list and press `Edit Selected` ### Expected Behavior changes applied successfully ### Observed Behavior following error message ``` <class 'TypeError'> fromisoformat: argument must be str Python version: 3.8.10 NetBox version: 3.4.2 ```
adam added the type: bugstatus: accepted labels 2025-12-29 20:23:34 +01:00
adam closed this issue 2025-12-29 20:23:34 +01:00
Author
Owner

@kkthxbye-code commented on GitHub (Jan 4, 2023):

Relevant stack trace:

Traceback (most recent call last):
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/main/devel/repos/netbox/netbox/netbox/views/generic/base.py", line 77, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/home/main/devel/repos/netbox/netbox/utilities/views.py", line 99, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 142, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/main/devel/repos/netbox/netbox/netbox/views/generic/bulk_views.py", line 595, in post
    updated_objects = self._update_objects(form, request)
  File "/home/main/devel/repos/netbox/netbox/netbox/views/generic/bulk_views.py", line 544, in _update_objects
    obj.save()
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/db/models/base.py", line 812, in save
    self.save_base(
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/db/models/base.py", line 878, in save_base
    post_save.send(
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/dispatch/dispatcher.py", line 176, in send
    return [
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/dispatch/dispatcher.py", line 177, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "/home/main/devel/repos/netbox/netbox/extras/signals.py", line 87, in handle_changed_object
    enqueue_object(queue, instance, request.user, request.id, action)
  File "/home/main/devel/repos/netbox/netbox/extras/webhooks.py", line 72, in enqueue_object
    'data': serialize_for_webhook(instance),
  File "/home/main/devel/repos/netbox/netbox/extras/webhooks.py", line 27, in serialize_for_webhook
    return serializer.data
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/rest_framework/serializers.py", line 555, in data
    ret = super().data
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/rest_framework/serializers.py", line 253, in data
    self._data = self.to_representation(self.instance)
  File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/rest_framework/serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "/home/main/devel/repos/netbox/netbox/extras/api/customfields.py", line 55, in to_representation
    value = cf.deserialize(obj.get(cf.name))
  File "/home/main/devel/repos/netbox/netbox/extras/models/customfields.py", line 321, in deserialize
    return date.fromisoformat(value)

The issue occurs when the custom field is deserialized when sent to the webhooks handler (no webhooks need to be registered). For some reason when saving the object normally the cf arrives at deserialize as a string, but when bulk editing it arrives as a Date object. Not sure what the proper fix is here - @jeremystretch or @arthanson can one of you guys take a look at it?

Adding TypeError to the exceptions here fixes it:

https://github.com/netbox-community/netbox/blob/develop/netbox/extras/models/customfields.py#L322

But I'm sure that's not the correct solution.

@kkthxbye-code commented on GitHub (Jan 4, 2023): Relevant stack trace: ``` Traceback (most recent call last): File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view return self.dispatch(request, *args, **kwargs) File "/home/main/devel/repos/netbox/netbox/netbox/views/generic/base.py", line 77, in dispatch return super().dispatch(request, *args, **kwargs) File "/home/main/devel/repos/netbox/netbox/utilities/views.py", line 99, in dispatch return super().dispatch(request, *args, **kwargs) File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 142, in dispatch return handler(request, *args, **kwargs) File "/home/main/devel/repos/netbox/netbox/netbox/views/generic/bulk_views.py", line 595, in post updated_objects = self._update_objects(form, request) File "/home/main/devel/repos/netbox/netbox/netbox/views/generic/bulk_views.py", line 544, in _update_objects obj.save() File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/db/models/base.py", line 812, in save self.save_base( File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/db/models/base.py", line 878, in save_base post_save.send( File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/dispatch/dispatcher.py", line 176, in send return [ File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/django/dispatch/dispatcher.py", line 177, in <listcomp> (receiver, receiver(signal=self, sender=sender, **named)) File "/home/main/devel/repos/netbox/netbox/extras/signals.py", line 87, in handle_changed_object enqueue_object(queue, instance, request.user, request.id, action) File "/home/main/devel/repos/netbox/netbox/extras/webhooks.py", line 72, in enqueue_object 'data': serialize_for_webhook(instance), File "/home/main/devel/repos/netbox/netbox/extras/webhooks.py", line 27, in serialize_for_webhook return serializer.data File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/rest_framework/serializers.py", line 555, in data ret = super().data File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/rest_framework/serializers.py", line 253, in data self._data = self.to_representation(self.instance) File "/home/main/devel/repos/netbox/venv/lib/python3.10/site-packages/rest_framework/serializers.py", line 522, in to_representation ret[field.field_name] = field.to_representation(attribute) File "/home/main/devel/repos/netbox/netbox/extras/api/customfields.py", line 55, in to_representation value = cf.deserialize(obj.get(cf.name)) File "/home/main/devel/repos/netbox/netbox/extras/models/customfields.py", line 321, in deserialize return date.fromisoformat(value) ``` The issue occurs when the custom field is deserialized when sent to the webhooks handler (no webhooks need to be registered). For some reason when saving the object normally the cf arrives at `deserialize` as a string, but when bulk editing it arrives as a Date object. Not sure what the proper fix is here - @jeremystretch or @arthanson can one of you guys take a look at it? Adding `TypeError` to the exceptions here fixes it: https://github.com/netbox-community/netbox/blob/develop/netbox/extras/models/customfields.py#L322 But I'm sure that's not the correct solution.
Author
Owner

@jeremystretch commented on GitHub (Jan 6, 2023):

I believe I've tracked this down to a caveat in how BulkEditView handles saving custom field data as compared to ObjectEditView: It's applying the native field value (in this case, a datetime object) rather than its serialized value. Fixing this appears to resolve the issue, but I also want to be sure I haven't inadvertently broken anything that relies on this nonstandard behavior.

@jeremystretch commented on GitHub (Jan 6, 2023): I believe I've tracked this down to a caveat in how BulkEditView handles saving custom field data as compared to ObjectEditView: It's applying the native field value (in this case, a `datetime` object) rather than its serialized value. Fixing this appears to resolve the issue, but I also want to be sure I haven't inadvertently broken anything that relies on this nonstandard behavior.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#7447