From 914653d63efa27f9dd8a2fb160518f63db05b755 Mon Sep 17 00:00:00 2001 From: Jason Novinger Date: Tue, 30 Dec 2025 09:35:19 -0600 Subject: [PATCH] Fixes #21045: Allow saving Site with associated Prefix This was a result of the fix for #20944 optimizing a query to only include the `id` field with `.only(id)`. Since `Prefix.__init__()` caches original values from other fields (`_prefix` and `_vrf_id`), these cached values are `None` at init-time. This might not normally be a problem, but the sequence of events in the bug report also end up causing the `handle_prefix_saved` handler to run, which uses an ORM lookup, (either `net_contained_or_equal` original`net_contained`) that does not support a query argument of `None`. --- netbox/dcim/signals.py | 2 +- netbox/dcim/tests/test_models.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index 68711eb9a..75536afb6 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -210,7 +210,7 @@ def sync_cached_scope_fields(instance, created, **kwargs): for model in (Prefix, Cluster, WirelessLAN): qs = model.objects.filter(**filters) - for obj in qs.only('id'): + for obj in qs: # Recompute cache using the same logic as save() obj.cache_related_objects() obj.save(update_fields=[ diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index f41509808..57da78372 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -6,6 +6,7 @@ from core.models import ObjectType from dcim.choices import * from dcim.models import * from extras.models import CustomField +from ipam.models import Prefix from netbox.choices import WeightUnitChoices from tenancy.models import Tenant from utilities.data import drange @@ -1192,3 +1193,14 @@ class VirtualChassisTestCase(TestCase): device2.vc_position = 1 with self.assertRaises(ValidationError): device2.full_clean() + + +class SiteSignalTestCase(TestCase): + + @tag('regression') + def test_edit_site_with_prefix_no_vrf(self): + site = Site.objects.create(name='Test Site', slug='test-site') + Prefix.objects.create(prefix='192.0.2.0/24', scope=site, vrf=None) + + # Regression test for #21045: should not raise ValueError + site.save()