mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-17 17:56:29 +00:00
Fixes #20290: Prevent ObjectType queries when table doesn't exist
In v4.4.0, ObjectType became a concrete model with a database table. Signal handlers query this table during migrations, but the table doesn't exist yet during 3.7.x→4.4.0 upgrades. The query failures poison the transaction and abort migrations. Added objecttype_table_exists() helper and three table existence checks: - has_feature() in netbox/models/features.py - update_object_types() in core/signals.py - Search backend cache() in search/backends.py If core_objecttype table doesn't exist, operations return early instead of querying. Once table exists, normal operation resumes.
This commit is contained in:
parent
f23eb53312
commit
52d990463f
@ -13,6 +13,7 @@ from django_prometheus.models import model_deletes, model_inserts, model_updates
|
||||
from core.choices import JobStatusChoices, ObjectChangeActionChoices
|
||||
from core.events import *
|
||||
from core.models import ObjectType
|
||||
from utilities.object_types import objecttype_table_exists
|
||||
from extras.events import enqueue_event
|
||||
from extras.models import Tag
|
||||
from extras.utils import run_validators
|
||||
@ -51,6 +52,10 @@ def update_object_types(sender, **kwargs):
|
||||
"""
|
||||
Create or update the corresponding ObjectType for each model within the migrated app.
|
||||
"""
|
||||
# Skip ObjectType operations if the table doesn't exist yet (during migrations)
|
||||
if not objecttype_table_exists():
|
||||
return
|
||||
|
||||
for model in sender.get_models():
|
||||
app_label, model_name = model._meta.label_lower.split('.')
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ from netbox.registry import registry
|
||||
from netbox.signals import post_clean
|
||||
from netbox.utils import register_model_feature
|
||||
from utilities.json import CustomFieldJSONEncoder
|
||||
from utilities.object_types import objecttype_table_exists
|
||||
from utilities.serialization import serialize_object
|
||||
|
||||
__all__ = (
|
||||
@ -670,6 +671,10 @@ def has_feature(model_or_ct, feature):
|
||||
"""
|
||||
Returns True if the model supports the specified feature.
|
||||
"""
|
||||
# Check if ObjectType table exists before attempting queries
|
||||
if not objecttype_table_exists():
|
||||
return False
|
||||
|
||||
# If an ObjectType was passed, we can use it directly
|
||||
if type(model_or_ct) is ObjectType:
|
||||
ot = model_or_ct
|
||||
|
||||
@ -15,6 +15,7 @@ from netaddr.core import AddrFormatError
|
||||
from core.models import ObjectType
|
||||
from extras.models import CachedValue, CustomField
|
||||
from netbox.registry import registry
|
||||
from utilities.object_types import objecttype_table_exists
|
||||
from utilities.object_types import object_type_identifier
|
||||
from utilities.querysets import RestrictedPrefetch
|
||||
from utilities.string import title
|
||||
@ -209,6 +210,10 @@ class CachedValueSearchBackend(SearchBackend):
|
||||
break
|
||||
|
||||
# Prefetch any associated custom fields
|
||||
# Skip if ObjectType table doesn't exist yet (during migrations)
|
||||
if not objecttype_table_exists():
|
||||
return
|
||||
|
||||
object_type = ObjectType.objects.get_for_model(indexer.model)
|
||||
custom_fields = CustomField.objects.filter(object_types=object_type).exclude(search_weight=0)
|
||||
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
from django.db import connection
|
||||
|
||||
from .string import title
|
||||
|
||||
__all__ = (
|
||||
'object_type_identifier',
|
||||
'object_type_name',
|
||||
'objecttype_table_exists',
|
||||
)
|
||||
|
||||
|
||||
@ -27,3 +30,13 @@ def object_type_name(object_type, include_app=True):
|
||||
except AttributeError:
|
||||
# Model does not exist
|
||||
return f'{object_type.app_label} > {object_type.model}'
|
||||
|
||||
|
||||
def objecttype_table_exists():
|
||||
"""
|
||||
Check if the core_objecttype table exists.
|
||||
|
||||
Returns True if the table exists, False otherwise.
|
||||
Used to prevent ObjectType queries during migrations when the table doesn't exist yet.
|
||||
"""
|
||||
return 'core_objecttype' in connection.introspection.table_names()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user