Просмотр исходного кода

Rename ContentType proxy model to ObjectType

Jeremy Stretch 1 год назад
Родитель
Сommit
0df68bf291

+ 1 - 1
netbox/core/forms/filtersets.py

@@ -68,7 +68,7 @@ class JobFilterForm(SavedFiltersMixin, FilterForm):
     )
     object_type = ContentTypeChoiceField(
         label=_('Object Type'),
-        queryset=ContentType.objects.with_feature('jobs'),
+        queryset=ObjectType.objects.with_feature('jobs'),
         required=False,
     )
     status = forms.MultipleChoiceField(

+ 2 - 2
netbox/core/management/commands/nbshell.py

@@ -8,7 +8,7 @@ from django.conf import settings
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 
-from core.models import ContentType
+from core.models import ObjectType
 
 APPS = ('circuits', 'core', 'dcim', 'extras', 'ipam', 'tenancy', 'users', 'virtualization', 'vpn', 'wireless')
 
@@ -60,7 +60,7 @@ class Command(BaseCommand):
                 pass
 
         # Additional objects to include
-        namespace['ContentType'] = ContentType
+        namespace['ObjectType'] = ObjectType
         namespace['User'] = get_user_model()
 
         # Load convenience commands

+ 2 - 4
netbox/core/migrations/0008_contenttype_proxy.py

@@ -1,5 +1,3 @@
-# Generated by Django 4.2.6 on 2023-10-31 19:38
-
 import core.models.contenttypes
 from django.db import migrations
 
@@ -13,7 +11,7 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.CreateModel(
-            name='ContentType',
+            name='ObjectType',
             fields=[
             ],
             options={
@@ -23,7 +21,7 @@ class Migration(migrations.Migration):
             },
             bases=('contenttypes.contenttype',),
             managers=[
-                ('objects', core.models.contenttypes.ContentTypeManager()),
+                ('objects', core.models.contenttypes.ObjectTypeManager()),
             ],
         ),
     ]

+ 6 - 6
netbox/core/models/contenttypes.py

@@ -1,15 +1,15 @@
-from django.contrib.contenttypes.models import ContentType as ContentType_, ContentTypeManager as ContentTypeManager_
+from django.contrib.contenttypes.models import ContentType, ContentTypeManager
 from django.db.models import Q
 
 from netbox.registry import registry
 
 __all__ = (
-    'ContentType',
-    'ContentTypeManager',
+    'ObjectType',
+    'ObjectTypeManager',
 )
 
 
-class ContentTypeManager(ContentTypeManager_):
+class ObjectTypeManager(ContentTypeManager):
 
     def public(self):
         """
@@ -40,11 +40,11 @@ class ContentTypeManager(ContentTypeManager_):
         return self.get_queryset().filter(q)
 
 
-class ContentType(ContentType_):
+class ObjectType(ContentType):
     """
     Wrap Django's native ContentType model to use our custom manager.
     """
-    objects = ContentTypeManager()
+    objects = ObjectTypeManager()
 
     class Meta:
         proxy = True

+ 3 - 3
netbox/core/models/jobs.py

@@ -11,7 +11,7 @@ from django.utils import timezone
 from django.utils.translation import gettext as _
 
 from core.choices import JobStatusChoices
-from core.models import ContentType
+from core.models import ObjectType
 from core.signals import job_end, job_start
 from extras.constants import EVENT_JOB_END, EVENT_JOB_START
 from netbox.config import get_config
@@ -130,7 +130,7 @@ class Job(models.Model):
         super().clean()
 
         # Validate the assigned object type
-        if self.object_type not in ContentType.objects.with_feature('jobs'):
+        if self.object_type not in ObjectType.objects.with_feature('jobs'):
             raise ValidationError(
                 _("Jobs cannot be assigned to this object type ({type}).").format(type=self.object_type)
             )
@@ -210,7 +210,7 @@ class Job(models.Model):
             schedule_at: Schedule the job to be executed at the passed date and time
             interval: Recurrence interval (in minutes)
         """
-        object_type = ContentType.objects.get_for_model(instance, for_concrete_model=False)
+        object_type = ObjectType.objects.get_for_model(instance, for_concrete_model=False)
         rq_queue_name = get_queue_for_model(object_type.model)
         queue = django_rq.get_queue(rq_queue_name)
         status = JobStatusChoices.STATUS_SCHEDULED if schedule_at else JobStatusChoices.STATUS_PENDING

+ 6 - 6
netbox/dcim/models/cables.py

@@ -9,7 +9,7 @@ from django.dispatch import Signal
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from dcim.choices import *
 from dcim.constants import *
 from dcim.fields import PathField
@@ -481,13 +481,13 @@ class CablePath(models.Model):
     def origin_type(self):
         if self.path:
             ct_id, _ = decompile_path_node(self.path[0][0])
-            return ContentType.objects.get_for_id(ct_id)
+            return ObjectType.objects.get_for_id(ct_id)
 
     @property
     def destination_type(self):
         if self.is_complete:
             ct_id, _ = decompile_path_node(self.path[-1][0])
-            return ContentType.objects.get_for_id(ct_id)
+            return ObjectType.objects.get_for_id(ct_id)
 
     @property
     def path_objects(self):
@@ -594,7 +594,7 @@ class CablePath(models.Model):
 
             # Step 6: Determine the far-end terminations
             if isinstance(links[0], Cable):
-                termination_type = ContentType.objects.get_for_model(terminations[0])
+                termination_type = ObjectType.objects.get_for_model(terminations[0])
                 local_cable_terminations = CableTermination.objects.filter(
                     termination_type=termination_type,
                     termination_id__in=[t.pk for t in terminations]
@@ -747,7 +747,7 @@ class CablePath(models.Model):
         # Prefetch path objects using one query per model type. Prefetch related devices where appropriate.
         prefetched = {}
         for ct_id, object_ids in to_prefetch.items():
-            model_class = ContentType.objects.get_for_id(ct_id).model_class()
+            model_class = ObjectType.objects.get_for_id(ct_id).model_class()
             queryset = model_class.objects.filter(pk__in=object_ids)
             if hasattr(model_class, 'device'):
                 queryset = queryset.prefetch_related('device')
@@ -774,7 +774,7 @@ class CablePath(models.Model):
         """
         Return all Cable IDs within the path.
         """
-        cable_ct = ContentType.objects.get_for_model(Cable).pk
+        cable_ct = ObjectType.objects.get_for_model(Cable).pk
         cable_ids = []
 
         for node in self._nodes:

+ 13 - 13
netbox/extras/api/serializers.py

@@ -7,7 +7,7 @@ from rest_framework import serializers
 
 from core.api.nested_serializers import NestedDataSourceSerializer, NestedDataFileSerializer, NestedJobSerializer
 from core.api.serializers import JobSerializer
-from core.models import ContentType
+from core.models import ObjectType
 from dcim.api.nested_serializers import (
     NestedDeviceRoleSerializer, NestedDeviceTypeSerializer, NestedLocationSerializer, NestedPlatformSerializer,
     NestedRegionSerializer, NestedSiteSerializer, NestedSiteGroupSerializer,
@@ -60,12 +60,12 @@ __all__ = (
 class EventRuleSerializer(NetBoxModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:eventrule-detail')
     content_types = ContentTypeField(
-        queryset=ContentType.objects.with_feature('event_rules'),
+        queryset=ObjectType.objects.with_feature('event_rules'),
         many=True
     )
     action_type = ChoiceField(choices=EventRuleActionChoices)
     action_object_type = ContentTypeField(
-        queryset=ContentType.objects.with_feature('event_rules'),
+        queryset=ObjectType.objects.with_feature('event_rules'),
     )
     action_object = serializers.SerializerMethodField(read_only=True)
 
@@ -118,12 +118,12 @@ class WebhookSerializer(NetBoxModelSerializer):
 class CustomFieldSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:customfield-detail')
     content_types = ContentTypeField(
-        queryset=ContentType.objects.with_feature('custom_fields'),
+        queryset=ObjectType.objects.with_feature('custom_fields'),
         many=True
     )
     type = ChoiceField(choices=CustomFieldTypeChoices)
     object_type = ContentTypeField(
-        queryset=ContentType.objects.all(),
+        queryset=ObjectType.objects.all(),
         required=False,
         allow_null=True
     )
@@ -197,7 +197,7 @@ class CustomFieldChoiceSetSerializer(ValidatedModelSerializer):
 class CustomLinkSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:customlink-detail')
     content_types = ContentTypeField(
-        queryset=ContentType.objects.with_feature('custom_links'),
+        queryset=ObjectType.objects.with_feature('custom_links'),
         many=True
     )
 
@@ -217,7 +217,7 @@ class CustomLinkSerializer(ValidatedModelSerializer):
 class ExportTemplateSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:exporttemplate-detail')
     content_types = ContentTypeField(
-        queryset=ContentType.objects.with_feature('export_templates'),
+        queryset=ObjectType.objects.with_feature('export_templates'),
         many=True
     )
     data_source = NestedDataSourceSerializer(
@@ -244,7 +244,7 @@ class ExportTemplateSerializer(ValidatedModelSerializer):
 class SavedFilterSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:savedfilter-detail')
     content_types = ContentTypeField(
-        queryset=ContentType.objects.all(),
+        queryset=ObjectType.objects.all(),
         many=True
     )
 
@@ -264,7 +264,7 @@ class SavedFilterSerializer(ValidatedModelSerializer):
 class BookmarkSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:bookmark-detail')
     object_type = ContentTypeField(
-        queryset=ContentType.objects.with_feature('bookmarks'),
+        queryset=ObjectType.objects.with_feature('bookmarks'),
     )
     object = serializers.SerializerMethodField(read_only=True)
     user = NestedUserSerializer()
@@ -289,7 +289,7 @@ class BookmarkSerializer(ValidatedModelSerializer):
 class TagSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:tag-detail')
     object_types = ContentTypeField(
-        queryset=ContentType.objects.with_feature('tags'),
+        queryset=ObjectType.objects.with_feature('tags'),
         many=True,
         required=False
     )
@@ -313,7 +313,7 @@ class TagSerializer(ValidatedModelSerializer):
 class ImageAttachmentSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:imageattachment-detail')
     content_type = ContentTypeField(
-        queryset=ContentType.objects.all()
+        queryset=ObjectType.objects.all()
     )
     parent = serializers.SerializerMethodField(read_only=True)
 
@@ -353,7 +353,7 @@ class ImageAttachmentSerializer(ValidatedModelSerializer):
 class JournalEntrySerializer(NetBoxModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:journalentry-detail')
     assigned_object_type = ContentTypeField(
-        queryset=ContentType.objects.all()
+        queryset=ObjectType.objects.all()
     )
     assigned_object = serializers.SerializerMethodField(read_only=True)
     created_by = serializers.PrimaryKeyRelatedField(
@@ -645,7 +645,7 @@ class ContentTypeSerializer(BaseModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:contenttype-detail')
 
     class Meta:
-        model = ContentType
+        model = ObjectType
         fields = ['id', 'url', 'display', 'app_label', 'model']
 
 

+ 6 - 6
netbox/extras/dashboard/widgets.py

@@ -12,7 +12,7 @@ from django.template.loader import render_to_string
 from django.urls import NoReverseMatch, resolve, reverse
 from django.utils.translation import gettext as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from extras.choices import BookmarkOrderingChoices
 from utilities.choices import ButtonColorChoices
 from utilities.permissions import get_permission_for_model
@@ -34,14 +34,14 @@ __all__ = (
 def get_object_type_choices():
     return [
         (content_type_identifier(ct), content_type_name(ct))
-        for ct in ContentType.objects.public().order_by('app_label', 'model')
+        for ct in ObjectType.objects.public().order_by('app_label', 'model')
     ]
 
 
 def get_bookmarks_object_type_choices():
     return [
         (content_type_identifier(ct), content_type_name(ct))
-        for ct in ContentType.objects.with_feature('bookmarks').order_by('app_label', 'model')
+        for ct in ObjectType.objects.with_feature('bookmarks').order_by('app_label', 'model')
     ]
 
 
@@ -52,7 +52,7 @@ def get_models_from_content_types(content_types):
     models = []
     for content_type_id in content_types:
         app_label, model_name = content_type_id.split('.')
-        content_type = ContentType.objects.get_by_natural_key(app_label, model_name)
+        content_type = ObjectType.objects.get_by_natural_key(app_label, model_name)
         models.append(content_type.model_class())
     return models
 
@@ -238,7 +238,7 @@ class ObjectListWidget(DashboardWidget):
 
     def render(self, request):
         app_label, model_name = self.config['model'].split('.')
-        model = ContentType.objects.get_by_natural_key(app_label, model_name).model_class()
+        model = ObjectType.objects.get_by_natural_key(app_label, model_name).model_class()
         viewname = get_viewname(model, action='list')
 
         # Evaluate user's permission. Note that this controls only whether the HTMX element is
@@ -371,7 +371,7 @@ class BookmarksWidget(DashboardWidget):
             bookmarks = Bookmark.objects.filter(user=request.user).order_by(self.config['order_by'])
             if object_types := self.config.get('object_types'):
                 models = get_models_from_content_types(object_types)
-                conent_types = ContentType.objects.get_for_models(*models).values()
+                conent_types = ObjectType.objects.get_for_models(*models).values()
                 bookmarks = bookmarks.filter(object_type__in=conent_types)
             if max_items := self.config.get('max_items'):
                 bookmarks = bookmarks[:max_items]

+ 9 - 9
netbox/extras/forms/bulk_import.py

@@ -6,7 +6,7 @@ from django.core.exceptions import ObjectDoesNotExist
 from django.utils.safestring import mark_safe
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from extras.choices import *
 from extras.models import *
 from netbox.forms import NetBoxModelImportForm
@@ -32,7 +32,7 @@ __all__ = (
 class CustomFieldImportForm(CSVModelForm):
     content_types = CSVMultipleContentTypeField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('custom_fields'),
+        queryset=ObjectType.objects.with_feature('custom_fields'),
         help_text=_("One or more assigned object types")
     )
     type = CSVChoiceField(
@@ -42,7 +42,7 @@ class CustomFieldImportForm(CSVModelForm):
     )
     object_type = CSVContentTypeField(
         label=_('Object type'),
-        queryset=ContentType.objects.public(),
+        queryset=ObjectType.objects.public(),
         required=False,
         help_text=_("Object type (for object or multi-object fields)")
     )
@@ -113,7 +113,7 @@ class CustomFieldChoiceSetImportForm(CSVModelForm):
 class CustomLinkImportForm(CSVModelForm):
     content_types = CSVMultipleContentTypeField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('custom_links'),
+        queryset=ObjectType.objects.with_feature('custom_links'),
         help_text=_("One or more assigned object types")
     )
 
@@ -128,7 +128,7 @@ class CustomLinkImportForm(CSVModelForm):
 class ExportTemplateImportForm(CSVModelForm):
     content_types = CSVMultipleContentTypeField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('export_templates'),
+        queryset=ObjectType.objects.with_feature('export_templates'),
         help_text=_("One or more assigned object types")
     )
 
@@ -151,7 +151,7 @@ class ConfigTemplateImportForm(CSVModelForm):
 class SavedFilterImportForm(CSVModelForm):
     content_types = CSVMultipleContentTypeField(
         label=_('Content types'),
-        queryset=ContentType.objects.all(),
+        queryset=ObjectType.objects.all(),
         help_text=_("One or more assigned object types")
     )
 
@@ -175,7 +175,7 @@ class WebhookImportForm(NetBoxModelImportForm):
 class EventRuleImportForm(NetBoxModelImportForm):
     content_types = CSVMultipleContentTypeField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('event_rules'),
+        queryset=ObjectType.objects.with_feature('event_rules'),
         help_text=_("One or more assigned object types")
     )
     action_object = forms.CharField(
@@ -213,7 +213,7 @@ class EventRuleImportForm(NetBoxModelImportForm):
                 except ObjectDoesNotExist:
                     raise forms.ValidationError(_("Script {name} not found").format(name=action_object))
                 self.instance.action_object = script
-                self.instance.action_object_type = ContentType.objects.get_for_model(script, for_concrete_model=False)
+                self.instance.action_object_type = ObjectType.objects.get_for_model(script, for_concrete_model=False)
 
 
 class TagImportForm(CSVModelForm):
@@ -229,7 +229,7 @@ class TagImportForm(CSVModelForm):
 
 class JournalEntryImportForm(NetBoxModelImportForm):
     assigned_object_type = CSVContentTypeField(
-        queryset=ContentType.objects.all(),
+        queryset=ObjectType.objects.all(),
         label=_('Assigned object type'),
     )
     kind = CSVChoiceField(

+ 11 - 11
netbox/extras/forms/filtersets.py

@@ -2,7 +2,7 @@ from django import forms
 from django.contrib.auth import get_user_model
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType, DataFile, DataSource
+from core.models import ObjectType, DataFile, DataSource
 from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
 from extras.choices import *
 from extras.models import *
@@ -43,7 +43,7 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
         )),
     )
     content_type_id = ContentTypeMultipleChoiceField(
-        queryset=ContentType.objects.with_feature('custom_fields'),
+        queryset=ObjectType.objects.with_feature('custom_fields'),
         required=False,
         label=_('Object type')
     )
@@ -112,7 +112,7 @@ class CustomLinkFilterForm(SavedFiltersMixin, FilterForm):
     )
     content_types = ContentTypeMultipleChoiceField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('custom_links'),
+        queryset=ObjectType.objects.with_feature('custom_links'),
         required=False
     )
     enabled = forms.NullBooleanField(
@@ -155,7 +155,7 @@ class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
         }
     )
     content_type_id = ContentTypeMultipleChoiceField(
-        queryset=ContentType.objects.with_feature('export_templates'),
+        queryset=ObjectType.objects.with_feature('export_templates'),
         required=False,
         label=_('Content types')
     )
@@ -183,7 +183,7 @@ class ImageAttachmentFilterForm(SavedFiltersMixin, FilterForm):
     )
     content_type_id = ContentTypeChoiceField(
         label=_('Content type'),
-        queryset=ContentType.objects.with_feature('image_attachments'),
+        queryset=ObjectType.objects.with_feature('image_attachments'),
         required=False
     )
     name = forms.CharField(
@@ -199,7 +199,7 @@ class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
     )
     content_types = ContentTypeMultipleChoiceField(
         label=_('Content types'),
-        queryset=ContentType.objects.public(),
+        queryset=ObjectType.objects.public(),
         required=False
     )
     enabled = forms.NullBooleanField(
@@ -254,7 +254,7 @@ class EventRuleFilterForm(NetBoxModelFilterSetForm):
         (_('Events'), ('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end')),
     )
     content_type_id = ContentTypeMultipleChoiceField(
-        queryset=ContentType.objects.with_feature('event_rules'),
+        queryset=ObjectType.objects.with_feature('event_rules'),
         required=False,
         label=_('Object type')
     )
@@ -310,12 +310,12 @@ class EventRuleFilterForm(NetBoxModelFilterSetForm):
 class TagFilterForm(SavedFiltersMixin, FilterForm):
     model = Tag
     content_type_id = ContentTypeMultipleChoiceField(
-        queryset=ContentType.objects.with_feature('tags'),
+        queryset=ObjectType.objects.with_feature('tags'),
         required=False,
         label=_('Tagged object type')
     )
     for_object_type_id = ContentTypeChoiceField(
-        queryset=ContentType.objects.with_feature('tags'),
+        queryset=ObjectType.objects.with_feature('tags'),
         required=False,
         label=_('Allowed object type')
     )
@@ -464,7 +464,7 @@ class JournalEntryFilterForm(NetBoxModelFilterSetForm):
         label=_('User')
     )
     assigned_object_type_id = DynamicModelMultipleChoiceField(
-        queryset=ContentType.objects.all(),
+        queryset=ObjectType.objects.all(),
         required=False,
         label=_('Object Type'),
         widget=APISelectMultiple(
@@ -507,7 +507,7 @@ class ObjectChangeFilterForm(SavedFiltersMixin, FilterForm):
         label=_('User')
     )
     changed_object_type_id = DynamicModelMultipleChoiceField(
-        queryset=ContentType.objects.all(),
+        queryset=ObjectType.objects.all(),
         required=False,
         label=_('Object Type'),
         widget=APISelectMultiple(

+ 11 - 11
netbox/extras/forms/model_forms.py

@@ -7,7 +7,7 @@ from django.utils.safestring import mark_safe
 from django.utils.translation import gettext_lazy as _
 
 from core.forms.mixins import SyncedDataMixin
-from core.models import ContentType
+from core.models import ObjectType
 from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
 from extras.choices import *
 from extras.models import *
@@ -41,11 +41,11 @@ __all__ = (
 class CustomFieldForm(forms.ModelForm):
     content_types = ContentTypeMultipleChoiceField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('custom_fields')
+        queryset=ObjectType.objects.with_feature('custom_fields')
     )
     object_type = ContentTypeChoiceField(
         label=_('Object type'),
-        queryset=ContentType.objects.public(),
+        queryset=ObjectType.objects.public(),
         required=False,
         help_text=_("Type of the related object (for object/multi-object fields only)")
     )
@@ -125,7 +125,7 @@ class CustomFieldChoiceSetForm(forms.ModelForm):
 class CustomLinkForm(forms.ModelForm):
     content_types = ContentTypeMultipleChoiceField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('custom_links')
+        queryset=ObjectType.objects.with_feature('custom_links')
     )
 
     fieldsets = (
@@ -154,7 +154,7 @@ class CustomLinkForm(forms.ModelForm):
 class ExportTemplateForm(SyncedDataMixin, forms.ModelForm):
     content_types = ContentTypeMultipleChoiceField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('export_templates')
+        queryset=ObjectType.objects.with_feature('export_templates')
     )
     template_code = forms.CharField(
         label=_('Template code'),
@@ -195,7 +195,7 @@ class SavedFilterForm(forms.ModelForm):
     slug = SlugField()
     content_types = ContentTypeMultipleChoiceField(
         label=_('Content types'),
-        queryset=ContentType.objects.all()
+        queryset=ObjectType.objects.all()
     )
     parameters = JSONField()
 
@@ -221,7 +221,7 @@ class SavedFilterForm(forms.ModelForm):
 class BookmarkForm(forms.ModelForm):
     object_type = ContentTypeChoiceField(
         label=_('Object type'),
-        queryset=ContentType.objects.with_feature('bookmarks')
+        queryset=ObjectType.objects.with_feature('bookmarks')
     )
 
     class Meta:
@@ -251,7 +251,7 @@ class WebhookForm(NetBoxModelForm):
 class EventRuleForm(NetBoxModelForm):
     content_types = ContentTypeMultipleChoiceField(
         label=_('Content types'),
-        queryset=ContentType.objects.with_feature('event_rules'),
+        queryset=ObjectType.objects.with_feature('event_rules'),
     )
     action_choice = forms.ChoiceField(
         label=_('Action choice'),
@@ -339,11 +339,11 @@ class EventRuleForm(NetBoxModelForm):
         action_choice = self.cleaned_data.get('action_choice')
         # Webhook
         if self.cleaned_data.get('action_type') == EventRuleActionChoices.WEBHOOK:
-            self.cleaned_data['action_object_type'] = ContentType.objects.get_for_model(action_choice)
+            self.cleaned_data['action_object_type'] = ObjectType.objects.get_for_model(action_choice)
             self.cleaned_data['action_object_id'] = action_choice.id
         # Script
         elif self.cleaned_data.get('action_type') == EventRuleActionChoices.SCRIPT:
-            self.cleaned_data['action_object_type'] = ContentType.objects.get_for_model(
+            self.cleaned_data['action_object_type'] = ObjectType.objects.get_for_model(
                 Script,
                 for_concrete_model=False
             )
@@ -356,7 +356,7 @@ class TagForm(forms.ModelForm):
     slug = SlugField()
     object_types = ContentTypeMultipleChoiceField(
         label=_('Object types'),
-        queryset=ContentType.objects.with_feature('tags'),
+        queryset=ObjectType.objects.with_feature('tags'),
         required=False
     )
 

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

@@ -5,7 +5,7 @@ from django.db import models
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from extras.choices import *
 from ..querysets import ObjectChangeQuerySet
 
@@ -113,7 +113,7 @@ class ObjectChange(models.Model):
         super().clean()
 
         # Validate the assigned object type
-        if self.changed_object_type not in ContentType.objects.with_feature('change_logging'):
+        if self.changed_object_type not in ObjectType.objects.with_feature('change_logging'):
             raise ValidationError(
                 _("Change logging is not supported for this object type ({type}).").format(
                     type=self.changed_object_type

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

@@ -12,7 +12,7 @@ from django.urls import reverse
 from django.utils.safestring import mark_safe
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from extras.choices import *
 from extras.data import CHOICE_SETS
 from netbox.models import ChangeLoggedModel
@@ -52,7 +52,7 @@ class CustomFieldManager(models.Manager.from_queryset(RestrictedQuerySet)):
         """
         Return all CustomFields assigned to the given model.
         """
-        content_type = ContentType.objects.get_for_model(model._meta.concrete_model)
+        content_type = ObjectType.objects.get_for_model(model._meta.concrete_model)
         return self.get_queryset().filter(content_types=content_type)
 
     def get_defaults_for_model(self, model):

+ 4 - 4
netbox/extras/models/models.py

@@ -12,7 +12,7 @@ from django.utils.formats import date_format
 from django.utils.translation import gettext_lazy as _
 from rest_framework.utils.encoders import JSONEncoder
 
-from core.models import ContentType
+from core.models import ObjectType
 from extras.choices import *
 from extras.conditions import ConditionSet
 from extras.constants import *
@@ -646,7 +646,7 @@ class ImageAttachment(ChangeLoggedModel):
         super().clean()
 
         # Validate the assigned object type
-        if self.content_type not in ContentType.objects.with_feature('image_attachments'):
+        if self.content_type not in ObjectType.objects.with_feature('image_attachments'):
             raise ValidationError(
                 _("Image attachments cannot be assigned to this object type ({type}).").format(type=self.content_type)
             )
@@ -739,7 +739,7 @@ class JournalEntry(CustomFieldsMixin, CustomLinksMixin, TagsMixin, ExportTemplat
         super().clean()
 
         # Validate the assigned object type
-        if self.assigned_object_type not in ContentType.objects.with_feature('journaling'):
+        if self.assigned_object_type not in ObjectType.objects.with_feature('journaling'):
             raise ValidationError(
                 _("Journaling is not supported for this object type ({type}).").format(type=self.assigned_object_type)
             )
@@ -795,7 +795,7 @@ class Bookmark(models.Model):
         super().clean()
 
         # Validate the assigned object type
-        if self.object_type not in ContentType.objects.with_feature('bookmarks'):
+        if self.object_type not in ObjectType.objects.with_feature('bookmarks'):
             raise ValidationError(
                 _("Bookmarks cannot be assigned to this object type ({type}).").format(type=self.object_type)
             )

+ 2 - 2
netbox/ipam/models/ip.py

@@ -8,7 +8,7 @@ from django.urls import reverse
 from django.utils.functional import cached_property
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from ipam.choices import *
 from ipam.constants import *
 from ipam.fields import IPNetworkField, IPAddressField
@@ -861,7 +861,7 @@ class IPAddress(PrimaryModel):
 
         if self._original_assigned_object_id and self._original_assigned_object_type_id:
             parent = getattr(self.assigned_object, 'parent_object', None)
-            ct = ContentType.objects.get_for_id(self._original_assigned_object_type_id)
+            ct = ObjectType.objects.get_for_id(self._original_assigned_object_type_id)
             original_assigned_object = ct.get_object_for_this_type(pk=self._original_assigned_object_id)
             original_parent = getattr(original_assigned_object, 'parent_object', None)
 

+ 3 - 3
netbox/netbox/models/features.py

@@ -10,7 +10,7 @@ from django.utils.translation import gettext_lazy as _
 from taggit.managers import TaggableManager
 
 from core.choices import JobStatusChoices
-from core.models import ContentType
+from core.models import ObjectType
 from extras.choices import *
 from extras.utils import is_taggable
 from netbox.config import get_config
@@ -490,7 +490,7 @@ class SyncedDataMixin(models.Model):
         ret = super().save(*args, **kwargs)
 
         # Create/delete AutoSyncRecord as needed
-        content_type = ContentType.objects.get_for_model(self)
+        content_type = ObjectType.objects.get_for_model(self)
         if self.auto_sync_enabled:
             AutoSyncRecord.objects.update_or_create(
                 object_type=content_type,
@@ -510,7 +510,7 @@ class SyncedDataMixin(models.Model):
         from core.models import AutoSyncRecord
 
         # Delete AutoSyncRecord
-        content_type = ContentType.objects.get_for_model(self)
+        content_type = ObjectType.objects.get_for_model(self)
         AutoSyncRecord.objects.filter(
             datafile=self.data_file,
             object_type=content_type,

+ 2 - 2
netbox/tenancy/forms/filtersets.py

@@ -1,7 +1,7 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from netbox.forms import NetBoxModelFilterSetForm
 from tenancy.choices import *
 from tenancy.models import *
@@ -86,7 +86,7 @@ class ContactAssignmentFilterForm(NetBoxModelFilterSetForm):
         (_('Assignment'), ('content_type_id', 'group_id', 'contact_id', 'role_id', 'priority')),
     )
     content_type_id = ContentTypeMultipleChoiceField(
-        queryset=ContentType.objects.with_feature('contacts'),
+        queryset=ObjectType.objects.with_feature('contacts'),
         required=False,
         label=_('Object type')
     )

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

@@ -4,7 +4,7 @@ from django.db import models
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from netbox.models import ChangeLoggedModel, NestedGroupModel, OrganizationalModel, PrimaryModel
 from netbox.models.features import CustomFieldsMixin, ExportTemplatesMixin, TagsMixin
 from tenancy.choices import *
@@ -165,7 +165,7 @@ class ContactAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, Chan
         super().clean()
 
         # Validate the assigned object type
-        if self.content_type not in ContentType.objects.with_feature('contacts'):
+        if self.content_type not in ObjectType.objects.with_feature('contacts'):
             raise ValidationError(
                 _("Contacts cannot be assigned to this object type ({type}).").format(type=self.content_type)
             )

+ 1 - 1
netbox/users/models.py

@@ -22,7 +22,7 @@ from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 from netaddr import IPNetwork
 
-from core.models import ContentType
+from core.models import ObjectType
 from ipam.fields import IPNetworkField
 from netbox.config import get_config
 from utilities.querysets import RestrictedQuerySet

+ 3 - 3
netbox/vpn/models/l2vpn.py

@@ -5,7 +5,7 @@ from django.urls import reverse
 from django.utils.functional import cached_property
 from django.utils.translation import gettext_lazy as _
 
-from core.models import ContentType
+from core.models import ObjectType
 from netbox.models import NetBoxModel, PrimaryModel
 from netbox.models.features import ContactsMixin
 from vpn.choices import L2VPNTypeChoices
@@ -128,7 +128,7 @@ class L2VPNTermination(NetBoxModel):
         # Only check is assigned_object is set.  Required otherwise we have an Integrity Error thrown.
         if self.assigned_object:
             obj_id = self.assigned_object.pk
-            obj_type = ContentType.objects.get_for_model(self.assigned_object)
+            obj_type = ObjectType.objects.get_for_model(self.assigned_object)
             if L2VPNTermination.objects.filter(assigned_object_id=obj_id, assigned_object_type=obj_type).\
                     exclude(pk=self.pk).count() > 0:
                 raise ValidationError(
@@ -150,7 +150,7 @@ class L2VPNTermination(NetBoxModel):
 
     @property
     def assigned_object_parent(self):
-        obj_type = ContentType.objects.get_for_model(self.assigned_object)
+        obj_type = ObjectType.objects.get_for_model(self.assigned_object)
         if obj_type.model == 'vminterface':
             return self.assigned_object.virtual_machine
         elif obj_type.model == 'interface':