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
+1 -1
View File
@@ -7,7 +7,7 @@ class NetBoxExportConfig(PluginConfig):
name = "netbox_export"
verbose_name = "NetBox-Export"
description = "Portable ZIP export and import for tenants and locations"
version = "0.3.4"
version = "0.3.5"
author = "NetBox Export contributors"
base_url = "netbox-export"
min_version = "4.6.0"
+1 -1
View File
@@ -39,7 +39,7 @@ def export_scope(
"created_at": datetime.now(UTC).isoformat(),
"source_instance": str(InstanceIdentity.local_id()),
"source_netbox_version": getattr(getattr(settings, "RELEASE", None), "version", "4.6"),
"plugin_version": "0.3.4",
"plugin_version": "0.3.5",
"scope": {
"type": scope_type,
"source_pk": str(scope_id),
+6 -2
View File
@@ -19,6 +19,7 @@ from .exceptions import ArchiveValidationError, ExportImportError, ImportConflic
from .plugin_compat import (
PluginCompatibility,
is_tenant_relation,
relation_required_before_save,
)
from .references import MISSING_REFERENCE, ReferenceResolver
@@ -245,16 +246,19 @@ def _field_kwargs(model, record, resolver, *, tenant_required: bool):
if not isinstance(field, (models.ForeignKey, models.OneToOneField)):
continue
tenant_relation = is_tenant_relation(field)
required_before_save = relation_required_before_save(field)
value, available = resolver.resolve(spec)
if available:
if value is MISSING_REFERENCE:
if not field.null and not field.has_default():
if (required_before_save and not tenant_relation) or (
not field.null and not field.has_default() and not tenant_relation
):
missing_required.append(name)
elif value is None and tenant_relation and tenant_required:
continue
else:
kwargs[name] = value
elif field.null and not tenant_relation:
elif field.null and not required_before_save:
unresolved.append((name, spec))
else:
return None, [], [], []
+28
View File
@@ -1,7 +1,10 @@
from __future__ import annotations
from functools import cache
from django.apps import apps
from django.core.exceptions import FieldDoesNotExist, ValidationError
from django.db import models
AUTO_IMPORT_TENANT_NAME = "Auto-Import"
AUTO_IMPORT_TENANT_SLUG = "auto-import"
@@ -24,6 +27,31 @@ def is_tenant_relation(field) -> bool:
return getattr(getattr(related_model, "_meta", None), "label_lower", None) == "tenancy.tenant"
def _condition_field_names(condition):
for child in getattr(condition, "children", ()):
if isinstance(child, tuple):
yield child[0].split("__", 1)[0]
else:
yield from _condition_field_names(child)
@cache
def check_constraint_field_names(model) -> frozenset[str]:
if model is None:
return frozenset()
names = set()
for constraint in model._meta.constraints:
if isinstance(constraint, models.CheckConstraint):
names.update(_condition_field_names(constraint.condition))
return frozenset(names)
def relation_required_before_save(field) -> bool:
return is_tenant_relation(field) or field.name in check_constraint_field_names(
getattr(field, "model", None)
)
class PluginCompatibility:
def __init__(
self,