瀏覽代碼

fix(models): Remove inert clone_fields from non-CloningMixin models

Removes clone_fields declarations from ContactAssignment,
ImageAttachment, and FHRPGroupAssignment models that don't inherit
CloningMixin.
Adds test coverage to prevent clone_fields on models without cloning
support.

Fixes #22987
Martin Hauser 1 天之前
父節點
當前提交
1184fa66a3

+ 0 - 2
netbox/extras/models/models.py

@@ -770,8 +770,6 @@ class ImageAttachment(ChangeLoggedModel):
 
 
     objects = RestrictedQuerySet.as_manager()
     objects = RestrictedQuerySet.as_manager()
 
 
-    clone_fields = ('object_type', 'object_id')
-
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)
 
 

+ 0 - 2
netbox/ipam/models/fhrp.py

@@ -103,8 +103,6 @@ class FHRPGroupAssignment(ChangeLoggedModel):
         )
         )
     )
     )
 
 
-    clone_fields = ('interface_type', 'interface_id')
-
     class Meta:
     class Meta:
         ordering = ('-priority', 'pk')
         ordering = ('-priority', 'pk')
         indexes = (
         indexes = (

+ 20 - 1
netbox/netbox/tests/test_model_features.py

@@ -1,5 +1,6 @@
 from unittest import skipIf
 from unittest import skipIf
 
 
+from django.apps import apps
 from django.conf import settings
 from django.conf import settings
 from django.test import TestCase
 from django.test import TestCase
 from taggit.models import Tag
 from taggit.models import Tag
@@ -8,7 +9,8 @@ from core.models import AutoSyncRecord, DataSource
 from dcim.models import Site
 from dcim.models import Site
 from extras.models import CustomLink
 from extras.models import CustomLink
 from ipam.models import Prefix
 from ipam.models import Prefix
-from netbox.models.features import get_model_features, has_feature, model_is_public
+from netbox.constants import CORE_APPS
+from netbox.models.features import CloningMixin, get_model_features, has_feature, model_is_public
 
 
 
 
 class ModelFeaturesTestCase(TestCase):
 class ModelFeaturesTestCase(TestCase):
@@ -62,6 +64,23 @@ class ModelFeaturesTestCase(TestCase):
         self.assertIn('cloning', features)
         self.assertIn('cloning', features)
         self.assertNotIn('bookmarks', features)
         self.assertNotIn('bookmarks', features)
 
 
+    def test_clone_fields_requires_cloning_support(self):
+        """
+        Check that only models which support the cloning feature declare clone_fields.
+        """
+        declaring = [
+            model for model in apps.get_models()
+            if model._meta.app_label in CORE_APPS and hasattr(model, 'clone_fields')
+        ]
+
+        # Sanity checking
+        self.assertIn(Prefix, declaring, "Invalid test?")
+
+        offenders = sorted(
+            model._meta.label for model in declaring if not issubclass(model, CloningMixin)
+        )
+        self.assertEqual(offenders, [], "clone_fields is inert on models which do not inherit CloningMixin")
+
     def test_cloningmixin_injects_gfk_attribute(self):
     def test_cloningmixin_injects_gfk_attribute(self):
         """
         """
         Tests the cloning mixin with GFK attribute injection in the `clone` method.
         Tests the cloning mixin with GFK attribute injection in the `clone` method.

+ 0 - 2
netbox/tenancy/models/contacts.py

@@ -154,8 +154,6 @@ class ContactAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, Chan
         null=True
         null=True
     )
     )
 
 
-    clone_fields = ('object_type', 'object_id', 'role', 'priority')
-
     class Meta:
     class Meta:
         ordering = ('contact', 'priority', 'role', 'pk')
         ordering = ('contact', 'priority', 'role', 'pk')
         indexes = (
         indexes = (