fix: resolve constrained relations before insert

This commit is contained in:
2026-08-05 13:46:59 +02:00
parent 985b66c96f
commit 3eb1729c93
8 changed files with 99 additions and 5 deletions
+40
View File
@@ -1,3 +1,5 @@
from typing import ClassVar
from django.db import models
from netbox_export.services.importer import _field_kwargs
@@ -16,6 +18,24 @@ class TenantManagedObject(models.Model):
app_label = "compat_tests"
class Platform(models.Model):
class Meta:
app_label = "compat_tests"
class ConstrainedInstallation(models.Model):
platform = models.ForeignKey(Platform, on_delete=models.PROTECT, null=True)
class Meta:
app_label = "compat_tests"
constraints: ClassVar[list] = [
models.CheckConstraint(
condition=models.Q(platform__isnull=False),
name="compat_tests_installation_platform",
)
]
def tenant_record():
return {
"fields": {},
@@ -53,3 +73,23 @@ def test_unresolved_tenant_also_blocks_when_policy_detection_is_unavailable():
assert unresolved == []
assert unresolved_values == []
assert missing_required == []
def test_unresolved_relation_in_check_constraint_blocks_initial_save():
resolver = ReferenceResolver({}, [], lambda label: None)
record = {
"fields": {},
"relations": {"platform": {"ref": "compat_tests.platform:5"}},
}
kwargs, unresolved, unresolved_values, missing_required = _field_kwargs(
ConstrainedInstallation,
record,
resolver,
tenant_required=False,
)
assert kwargs is None
assert unresolved == []
assert unresolved_values == []
assert missing_required == []
+19
View File
@@ -1,11 +1,14 @@
from types import SimpleNamespace
from django.core.exceptions import FieldDoesNotExist, ValidationError
from django.db import models
from netbox_export.services.plugin_compat import (
MISSING_TENANT_MESSAGE,
PluginCompatibility,
check_constraint_field_names,
is_tenant_relation,
relation_required_before_save,
)
@@ -82,6 +85,22 @@ def test_identifies_tenant_relation():
assert is_tenant_relation(relation_field("site", "dcim.site")) is False
def test_identifies_relations_used_by_check_constraint():
constraint = models.CheckConstraint(
condition=(
models.Q(device__isnull=False, virtualmachine__isnull=True)
| models.Q(device__isnull=True, virtualmachine__isnull=False)
),
name="platform",
)
model = type("ConstrainedModel", (), {"_meta": SimpleNamespace(constraints=[constraint])})
field = relation_field("device", "dcim.device")
field.model = model
assert check_constraint_field_names(model) == frozenset({"device", "virtualmachine"})
assert relation_required_before_save(field) is True
def test_creates_and_assigns_auto_import_tenant_when_policy_is_active():
manager = FakeTenantManager()
tenant_model = type("TenantModel", (), {"_default_manager": manager})