Skip to content

Commit 7231f9f

Browse files
authored
Merge pull request #146 from netboxlabs/NPL-373-changelog
NPL-373 fix changelog registration
2 parents b32ed25 + 8b9ffa2 commit 7231f9f

File tree

1 file changed

+63
-20
lines changed

1 file changed

+63
-20
lines changed

netbox_custom_objects/__init__.py

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,36 @@ def is_running_migration():
1818
return False
1919

2020

21+
def is_in_clear_cache():
22+
"""
23+
Check if the code is currently being called from Django's clear_cache() method.
24+
25+
TODO: This is fairly ugly, but in models.CustomObjectType.get_model() we call
26+
meta = type() which calls clear_cache on the model which causes a call to
27+
get_models() which in-turn calls get_model and therefore recurses.
28+
29+
This catches the specific case of a recursive call to get_models() from
30+
clear_cache() which is the only case we care about, so should be relatively
31+
safe. An alternative should be found for this.
32+
"""
33+
import inspect
34+
35+
frame = inspect.currentframe()
36+
try:
37+
# Walk up the call stack to see if we're being called from clear_cache
38+
while frame:
39+
if (
40+
frame.f_code.co_name == "clear_cache"
41+
and "django/apps/registry.py" in frame.f_code.co_filename
42+
):
43+
return True
44+
frame = frame.f_back
45+
return False
46+
finally:
47+
# Clean up the frame reference
48+
del frame
49+
50+
2151
def check_custom_object_type_table_exists():
2252
"""
2353
Check if the CustomObjectType table exists in the database.
@@ -49,6 +79,7 @@ class CustomObjectsPluginConfig(PluginConfig):
4979
default_settings = {}
5080
required_settings = []
5181
template_extensions = "template_content.template_extensions"
82+
_in_get_models = False # Recursion guard
5283

5384
def get_model(self, model_name, require_ready=True):
5485
try:
@@ -84,33 +115,45 @@ def get_model(self, model_name, require_ready=True):
84115

85116
def get_models(self, include_auto_created=False, include_swapped=False):
86117
"""Return all models for this plugin, including custom object type models."""
118+
87119
# Get the regular Django models first
88120
for model in super().get_models(include_auto_created, include_swapped):
89121
yield model
90122

91-
# Suppress warnings about database calls during model loading
92-
with warnings.catch_warnings():
93-
warnings.filterwarnings(
94-
"ignore", category=RuntimeWarning, message=".*database.*"
95-
)
96-
warnings.filterwarnings(
97-
"ignore", category=UserWarning, message=".*database.*"
98-
)
123+
# Prevent recursion
124+
if self._in_get_models and is_in_clear_cache():
125+
# Skip dynamic model creation if we're in a recursive get_models call
126+
return
99127

100-
# Skip custom object type model loading if running during migration
101-
if is_running_migration() or not check_custom_object_type_table_exists():
102-
return
103-
104-
# Add custom object type models
105-
from .models import CustomObjectType
106-
107-
custom_object_types = CustomObjectType.objects.all()
108-
for custom_type in custom_object_types:
109-
# Only yield already cached models during discovery
110-
if CustomObjectType.is_model_cached(custom_type.id):
111-
model = CustomObjectType.get_cached_model(custom_type.id)
128+
self._in_get_models = True
129+
try:
130+
# Suppress warnings about database calls during model loading
131+
with warnings.catch_warnings():
132+
warnings.filterwarnings(
133+
"ignore", category=RuntimeWarning, message=".*database.*"
134+
)
135+
warnings.filterwarnings(
136+
"ignore", category=UserWarning, message=".*database.*"
137+
)
138+
139+
# Skip custom object type model loading if running during migration
140+
if (
141+
is_running_migration()
142+
or not check_custom_object_type_table_exists()
143+
):
144+
return
145+
146+
# Add custom object type models
147+
from .models import CustomObjectType
148+
149+
custom_object_types = CustomObjectType.objects.all()
150+
for custom_type in custom_object_types:
151+
model = custom_type.get_model()
112152
if model:
113153
yield model
154+
finally:
155+
# Clean up the recursion guard
156+
self._in_get_models = False
114157

115158

116159
config = CustomObjectsPluginConfig

0 commit comments

Comments
 (0)