1
1
import sys
2
+ import warnings
2
3
3
4
from django .core .exceptions import AppRegistryNotReady
5
+ from django .db import transaction
6
+ from django .db .utils import DatabaseError , OperationalError , ProgrammingError
4
7
from netbox .plugins import PluginConfig
5
8
6
9
@@ -9,12 +12,32 @@ def is_running_migration():
9
12
Check if the code is currently running during a Django migration.
10
13
"""
11
14
# Check if 'makemigrations' or 'migrate' command is in sys.argv
12
- if any (cmd in sys .argv for cmd in [' makemigrations' , ' migrate' ]):
15
+ if any (cmd in sys .argv for cmd in [" makemigrations" , " migrate" ]):
13
16
return True
14
17
15
18
return False
16
19
17
20
21
+ def check_custom_object_type_table_exists ():
22
+ """
23
+ Check if the CustomObjectType table exists in the database.
24
+ Returns True if the table exists, False otherwise.
25
+ """
26
+ from .models import CustomObjectType
27
+
28
+ try :
29
+ # Try to query the model - if the table doesn't exist, this will raise an exception
30
+ # this check and the transaction.atomic() is only required when running tests as the
31
+ # migration check doesn't work correctly in the test environment
32
+ with transaction .atomic ():
33
+ # Force immediate execution by using first()
34
+ CustomObjectType .objects .first ()
35
+ return True
36
+ except (OperationalError , ProgrammingError , DatabaseError ):
37
+ # Catch database-specific errors (table doesn't exist, permission issues, etc.)
38
+ return False
39
+
40
+
18
41
# Plugin Configuration
19
42
class CustomObjectsPluginConfig (PluginConfig ):
20
43
name = "netbox_custom_objects"
@@ -59,37 +82,35 @@ def get_model(self, model_name, require_ready=True):
59
82
60
83
return obj .get_model ()
61
84
62
- # def get_models(self, include_auto_created=False, include_swapped=False):
63
- # """Return all models for this plugin, including custom object type models."""
64
- # # Get the regular Django models first
65
- # for model in super().get_models(include_auto_created, include_swapped):
66
- # yield model
67
- #
68
- # # Skip custom object type model loading if running during migration
69
- # if is_running_migration():
70
- # return
71
- #
72
- # # Suppress warnings about database calls during model loading
73
- # with warnings.catch_warnings():
74
- # warnings.filterwarnings(
75
- # "ignore", category=RuntimeWarning, message=".*database.*"
76
- # )
77
- # warnings.filterwarnings(
78
- # "ignore", category=UserWarning, message=".*database.*"
79
- # )
80
- #
81
- # # Add custom object type models
82
- # from .models import CustomObjectType
83
- #
84
- # # Only load models that are already cached to avoid creating all models at startup
85
- # # This prevents the "two TaggableManagers with same through model" error
86
- # custom_object_types = CustomObjectType.objects.all()
87
- # for custom_type in custom_object_types:
88
- # # Only yield already cached models during discovery
89
- # if CustomObjectType.is_model_cached(custom_type.id):
90
- # model = CustomObjectType.get_cached_model(custom_type.id)
91
- # if model:
92
- # yield model
85
+ def get_models (self , include_auto_created = False , include_swapped = False ):
86
+ """Return all models for this plugin, including custom object type models."""
87
+ # Get the regular Django models first
88
+ for model in super ().get_models (include_auto_created , include_swapped ):
89
+ yield model
90
+
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
+ )
99
+
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 )
112
+ if model :
113
+ yield model
93
114
94
115
95
116
config = CustomObjectsPluginConfig
0 commit comments