NaturalOrderingField does not update the instance during pre_save #3336

Closed
opened 2025-12-29 18:27:52 +01:00 by adam · 3 comments
Owner

Originally created by @hSaria on GitHub (Feb 16, 2020).

Environment

  • Python version: 3.6.9
  • NetBox version: 2.7.6

Steps to Reproduce

  1. Create device (/dcim/devices/add/) with name cs-01
  2. Edit the same device, change the name to something-cs-01, then save
  3. Edit the same device, do not change anything, then save

Expected Behavior

In the change logs created in response to the steps above, the name and _name fields should match.

Observed Behavior

The _name field lags behind the name one, like so:

Change log for step 1 (create):

    "_name": null,
    ...
    "name": "cs-01",

Change log for step 2 (update with change):

    "_name": "cs-00000001",
    ...
    "name": "something-cs-01",

Change log for step 3 (update without change):

    "_name": "something-cs-00000001",
    ...
    "name": "something-cs-01",
Originally created by @hSaria on GitHub (Feb 16, 2020). ### Environment * Python version: 3.6.9 * NetBox version: 2.7.6 ### Steps to Reproduce 1. Create device (`/dcim/devices/add/`) with name `cs-01` 2. Edit the same device, change the name to `something-cs-01`, then save 3. Edit the same device, do not change anything, then save ### Expected Behavior In the change logs created in response to the steps above, the `name` and `_name` fields should match. ### Observed Behavior The `_name` field lags behind the `name` one, like so: Change log for step 1 (create): ``` "_name": null, ... "name": "cs-01", ``` Change log for step 2 (update with change): ``` "_name": "cs-00000001", ... "name": "something-cs-01", ``` Change log for step 3 (update without change): ``` "_name": "something-cs-00000001", ... "name": "something-cs-01", ```
adam added the type: bugstatus: accepted labels 2025-12-29 18:27:52 +01:00
adam closed this issue 2025-12-29 18:27:52 +01:00
Author
Owner

@hSaria commented on GitHub (Feb 16, 2020):

In Django's documentation regarding preprocessing values before saving, they state:

You should also update the model’s attribute if you make any changes to the value so that code holding references to the model will always see the correct value."

The fix here is

diff --git a/netbox/utilities/fields.py b/netbox/utilities/fields.py
index 6181a7ca..e289f795 100644
--- a/netbox/utilities/fields.py
+++ b/netbox/utilities/fields.py
@@ -57,7 +57,9 @@ class NaturalOrderingField(models.CharField):
         Generate a naturalized value from the target field
         """
         value = getattr(model_instance, self.target_field)
-        return self.naturalize_function(value, max_length=self.max_length)
+        value = self.naturalize_function(value, max_length=self.max_length)
+        setattr(model_instance, self.attname, value)
+        return value
 
     def deconstruct(self):
         kwargs = super().deconstruct()[3]  # Pass kwargs from CharField

An example of this can be found on Django's DateField

@hSaria commented on GitHub (Feb 16, 2020): In [Django's documentation](https://docs.djangoproject.com/en/3.0/howto/custom-model-fields/#preprocessing-values-before-saving) regarding preprocessing values before saving, they state: > You should also update the model’s attribute if you make any changes to the value so that code holding references to the model will always see the correct value." The fix here is ```diff diff --git a/netbox/utilities/fields.py b/netbox/utilities/fields.py index 6181a7ca..e289f795 100644 --- a/netbox/utilities/fields.py +++ b/netbox/utilities/fields.py @@ -57,7 +57,9 @@ class NaturalOrderingField(models.CharField): Generate a naturalized value from the target field """ value = getattr(model_instance, self.target_field) - return self.naturalize_function(value, max_length=self.max_length) + value = self.naturalize_function(value, max_length=self.max_length) + setattr(model_instance, self.attname, value) + return value def deconstruct(self): kwargs = super().deconstruct()[3] # Pass kwargs from CharField ``` An example of this can be found on Django's [`DateField`](https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L1190-L1196)
Author
Owner

@jeremystretch commented on GitHub (Feb 17, 2020):

We should fix this, but it also raises the question of whether we should be logging _name at all.

@jeremystretch commented on GitHub (Feb 17, 2020): We should fix this, but it also raises the question of whether we should be logging `_name` at all.
Author
Owner

@hSaria commented on GitHub (Feb 17, 2020):

Agreed. There are other models that log private/internal fields in the change log, too. Maybe we could add an additional keyword argument to utilities.utils.serialize_object to remove keys out of serialized object?

@hSaria commented on GitHub (Feb 17, 2020): Agreed. There are other models that log private/internal fields in the change log, too. Maybe we could add an additional keyword argument to `utilities.utils.serialize_object` to remove keys out of serialized object?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#3336