From 0419a69ae8236f367cae26bf8fca1eed7fe2b7d5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 4 Mar 2024 10:46:34 -0500 Subject: [PATCH] Clean up outdated references to ContentType --- netbox/dcim/tests/test_views.py | 2 -- netbox/extras/api/customfields.py | 10 +++++----- netbox/extras/signals.py | 4 ++-- netbox/extras/tests/test_filtersets.py | 14 ++++++-------- netbox/extras/tests/test_forms.py | 7 +++---- netbox/netbox/api/serializers/features.py | 2 -- netbox/netbox/api/viewsets/mixins.py | 5 ++--- netbox/netbox/forms/base.py | 11 ++++++----- netbox/netbox/forms/mixins.py | 7 +++---- netbox/netbox/search/backends.py | 16 ++++++++-------- netbox/netbox/views/generic/bulk_views.py | 6 +++--- netbox/tenancy/tests/test_filtersets.py | 4 ++-- netbox/users/api/nested_serializers.py | 4 ++-- netbox/users/tests/test_filtersets.py | 3 +-- netbox/users/tests/test_views.py | 7 +++---- netbox/utilities/templatetags/helpers.py | 8 ++++---- netbox/utilities/tests/test_counters.py | 4 +--- 17 files changed, 51 insertions(+), 63 deletions(-) diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 53d7f3d34..e9e5a557b 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -3,7 +3,6 @@ from zoneinfo import ZoneInfo import yaml from django.contrib.auth import get_user_model -from django.contrib.contenttypes.models import ContentType from django.test import override_settings from django.urls import reverse from netaddr import EUI @@ -2982,7 +2981,6 @@ class CableTestCase( tags = create_tags('Alpha', 'Bravo', 'Charlie') - interface_ct = ContentType.objects.get_for_model(Interface) cls.form_data = { # TODO: Revisit this limitation # Changing terminations not supported when editing an existing Cable diff --git a/netbox/extras/api/customfields.py b/netbox/extras/api/customfields.py index 77c3a170e..7ecee01f8 100644 --- a/netbox/extras/api/customfields.py +++ b/netbox/extras/api/customfields.py @@ -1,10 +1,10 @@ -from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext as _ from drf_spectacular.utils import extend_schema_field from drf_spectacular.types import OpenApiTypes from rest_framework.fields import Field from rest_framework.serializers import ValidationError +from core.models import ObjectType from extras.choices import CustomFieldTypeChoices from extras.models import CustomField from netbox.constants import NESTED_SERIALIZER_PREFIX @@ -25,8 +25,8 @@ class CustomFieldDefaultValues: self.model = serializer_field.parent.Meta.model # Retrieve the CustomFields for the parent model - content_type = ContentType.objects.get_for_model(self.model) - fields = CustomField.objects.filter(object_types=content_type) + object_type = ObjectType.objects.get_for_model(self.model) + fields = CustomField.objects.filter(object_types=object_type) # Populate the default value for each CustomField value = {} @@ -47,8 +47,8 @@ class CustomFieldsDataField(Field): Cache CustomFields assigned to this model to avoid redundant database queries """ if not hasattr(self, '_custom_fields'): - content_type = ContentType.objects.get_for_model(self.parent.Meta.model) - self._custom_fields = CustomField.objects.filter(object_types=content_type) + object_type = ObjectType.objects.get_for_model(self.parent.Meta.model) + self._custom_fields = CustomField.objects.filter(object_types=object_type) return self._custom_fields def to_representation(self, obj): diff --git a/netbox/extras/signals.py b/netbox/extras/signals.py index cacc5a83a..833ce0036 100644 --- a/netbox/extras/signals.py +++ b/netbox/extras/signals.py @@ -257,7 +257,7 @@ def process_job_start_event_rules(sender, **kwargs): """ Process event rules for jobs starting. """ - event_rules = EventRule.objects.filter(type_job_start=True, enabled=True, content_types=sender.object_type) + event_rules = EventRule.objects.filter(type_job_start=True, enabled=True, object_types=sender.object_type) username = sender.user.username if sender.user else None process_event_rules(event_rules, sender.object_type.model, EVENT_JOB_START, sender.data, username) @@ -267,6 +267,6 @@ def process_job_end_event_rules(sender, **kwargs): """ Process event rules for jobs terminating. """ - event_rules = EventRule.objects.filter(type_job_end=True, enabled=True, content_types=sender.object_type) + event_rules = EventRule.objects.filter(type_job_end=True, enabled=True, object_types=sender.object_type) username = sender.user.username if sender.user else None process_event_rules(event_rules, sender.object_type.model, EVENT_JOB_END, sender.data, username) diff --git a/netbox/extras/tests/test_filtersets.py b/netbox/extras/tests/test_filtersets.py index 7be00a5a3..cec0ffe94 100644 --- a/netbox/extras/tests/test_filtersets.py +++ b/netbox/extras/tests/test_filtersets.py @@ -175,8 +175,6 @@ class WebhookTestCase(TestCase, BaseFilterSetTests): @classmethod def setUpTestData(cls): - content_types = ContentType.objects.filter(model__in=['region', 'site', 'rack', 'location', 'device']) - webhooks = ( Webhook( name='Webhook 1', @@ -355,7 +353,7 @@ class EventRuleTestCase(TestCase, BaseFilterSetTests): def test_object_types(self): params = {'object_types': 'dcim.region'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - params = {'object_types_id': [ContentType.objects.get_for_model(Region).pk]} + params = {'object_types_id': [ObjectType.objects.get_for_model(Region).pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_action_type(self): @@ -440,7 +438,7 @@ class CustomLinkTestCase(TestCase, BaseFilterSetTests): def test_object_types(self): params = {'object_types': 'dcim.site'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - params = {'object_types_id': [ContentType.objects.get_for_model(Site).pk]} + params = {'object_types_id': [ObjectType.objects.get_for_model(Site).pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_weight(self): @@ -530,7 +528,7 @@ class SavedFilterTestCase(TestCase, BaseFilterSetTests): def test_object_types(self): params = {'object_types': 'dcim.site'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - params = {'object_types_id': [ContentType.objects.get_for_model(Site).pk]} + params = {'object_types_id': [ObjectType.objects.get_for_model(Site).pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_user(self): @@ -661,7 +659,7 @@ class ExportTemplateTestCase(TestCase, BaseFilterSetTests): def test_object_types(self): params = {'object_types': 'dcim.site'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - params = {'object_types_id': [ContentType.objects.get_for_model(Site).pk]} + params = {'object_types_id': [ObjectType.objects.get_for_model(Site).pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_description(self): @@ -1164,12 +1162,12 @@ class TagTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_object_types(self): - params = {'for_object_type_id': [ContentType.objects.get_by_natural_key('dcim', 'site').pk]} + params = {'for_object_type_id': [ObjectType.objects.get_by_natural_key('dcim', 'site').pk]} self.assertEqual( list(self.filterset(params, self.queryset).qs.values_list('name', flat=True)), ['Tag 1', 'Tag 3'] ) - params = {'for_object_type_id': [ContentType.objects.get_by_natural_key('circuits', 'provider').pk]} + params = {'for_object_type_id': [ObjectType.objects.get_by_natural_key('circuits', 'provider').pk]} self.assertEqual( list(self.filterset(params, self.queryset).qs.values_list('name', flat=True)), ['Tag 2', 'Tag 3'] diff --git a/netbox/extras/tests/test_forms.py b/netbox/extras/tests/test_forms.py index 7642ee2a8..4c96e72d6 100644 --- a/netbox/extras/tests/test_forms.py +++ b/netbox/extras/tests/test_forms.py @@ -1,4 +1,3 @@ -from django.contrib.contenttypes.models import ContentType from django.test import TestCase from core.models import ObjectType @@ -63,14 +62,14 @@ class CustomFieldModelFormTest(TestCase): cf_object = CustomField.objects.create( name='object', type=CustomFieldTypeChoices.TYPE_OBJECT, - object_type=ContentType.objects.get_for_model(Site) + object_type=ObjectType.objects.get_for_model(Site) ) cf_object.object_types.set([object_type]) cf_multiobject = CustomField.objects.create( name='multiobject', type=CustomFieldTypeChoices.TYPE_MULTIOBJECT, - object_type=ContentType.objects.get_for_model(Site) + object_type=ObjectType.objects.get_for_model(Site) ) cf_multiobject.object_types.set([object_type]) @@ -100,7 +99,7 @@ class SavedFilterFormTest(TestCase): form = SavedFilterForm({ 'name': 'test-sf', 'slug': 'test-sf', - 'object_types': [ContentType.objects.get_for_model(Site).pk], + 'object_types': [ObjectType.objects.get_for_model(Site).pk], 'weight': 100, 'parameters': { "status": [ diff --git a/netbox/netbox/api/serializers/features.py b/netbox/netbox/api/serializers/features.py index 1374ba526..3bd5c8a2d 100644 --- a/netbox/netbox/api/serializers/features.py +++ b/netbox/netbox/api/serializers/features.py @@ -1,9 +1,7 @@ -from django.contrib.contenttypes.models import ContentType from rest_framework import serializers from rest_framework.fields import CreateOnlyDefault from extras.api.customfields import CustomFieldsDataField, CustomFieldDefaultValues -from extras.models import CustomField from .nested import NestedTagSerializer __all__ = ( diff --git a/netbox/netbox/api/viewsets/mixins.py b/netbox/netbox/api/viewsets/mixins.py index 7df498ac6..e07e2c78b 100644 --- a/netbox/netbox/api/viewsets/mixins.py +++ b/netbox/netbox/api/viewsets/mixins.py @@ -1,4 +1,3 @@ -from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist from django.db import transaction from django.http import Http404 @@ -41,8 +40,8 @@ class ExportTemplatesMixin: """ def list(self, request, *args, **kwargs): if 'export' in request.GET: - content_type = ContentType.objects.get_for_model(self.get_serializer_class().Meta.model) - et = ExportTemplate.objects.filter(content_types=content_type, name=request.GET['export']).first() + object_type = ObjectType.objects.get_for_model(self.get_serializer_class().Meta.model) + et = ExportTemplate.objects.filter(object_types=object_type, name=request.GET['export']).first() if et is None: raise Http404 queryset = self.filter_queryset(self.get_queryset()) diff --git a/netbox/netbox/forms/base.py b/netbox/netbox/forms/base.py index 12de3b12b..85064e79d 100644 --- a/netbox/netbox/forms/base.py +++ b/netbox/netbox/forms/base.py @@ -3,6 +3,7 @@ from django.contrib.contenttypes.models import ContentType from django.db.models import Q from django.utils.translation import gettext_lazy as _ +from core.models import ObjectType from extras.choices import * from extras.models import CustomField, Tag from utilities.forms import CSVModelForm @@ -129,9 +130,9 @@ class NetBoxModelBulkEditForm(CustomFieldsMixin, forms.Form): self.fields['pk'].queryset = self.model.objects.all() # Restrict tag fields by model - ct = ContentType.objects.get_for_model(self.model) - self.fields['add_tags'].widget.add_query_param('for_object_type_id', ct.pk) - self.fields['remove_tags'].widget.add_query_param('for_object_type_id', ct.pk) + object_type = ObjectType.objects.get_for_model(self.model) + self.fields['add_tags'].widget.add_query_param('for_object_type_id', object_type.pk) + self.fields['remove_tags'].widget.add_query_param('for_object_type_id', object_type.pk) self._extend_nullable_fields() @@ -169,9 +170,9 @@ class NetBoxModelFilterSetForm(CustomFieldsMixin, SavedFiltersMixin, forms.Form) super().__init__(*args, **kwargs) # Limit saved filters to those applicable to the form's model - content_type = ContentType.objects.get_for_model(self.model) + object_type = ObjectType.objects.get_for_model(self.model) self.fields['filter_id'].widget.add_query_params({ - 'content_type_id': content_type.pk, + 'object_types_id': object_type.pk, }) def _get_custom_fields(self, content_type): diff --git a/netbox/netbox/forms/mixins.py b/netbox/netbox/forms/mixins.py index 2f903db5d..6b1f31265 100644 --- a/netbox/netbox/forms/mixins.py +++ b/netbox/netbox/forms/mixins.py @@ -1,5 +1,4 @@ from django import forms -from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext as _ from core.models import ObjectType @@ -86,6 +85,6 @@ class TagsMixin(forms.Form): super().__init__(*args, **kwargs) # Limit tags to those applicable to the object type - content_type = ContentType.objects.get_for_model(self._meta.model) - if content_type and hasattr(self.fields['tags'].widget, 'add_query_param'): - self.fields['tags'].widget.add_query_param('for_object_type_id', content_type.pk) + object_type = ObjectType.objects.get_for_model(self._meta.model) + if object_type and hasattr(self.fields['tags'].widget, 'add_query_param'): + self.fields['tags'].widget.add_query_param('for_object_type_id', object_type.pk) diff --git a/netbox/netbox/search/backends.py b/netbox/netbox/search/backends.py index 0d7667087..a9e867b9f 100644 --- a/netbox/netbox/search/backends.py +++ b/netbox/netbox/search/backends.py @@ -131,11 +131,11 @@ class CachedValueSearchBackend(SearchBackend): ) )[:MAX_RESULTS] - # Gather all ContentTypes present in the search results (used for prefetching related + # Gather all ObjectTypes present in the search results (used for prefetching related # objects). This must be done before generating the final results list, which returns # a RawQuerySet. - content_type_ids = set(queryset.values_list('object_type', flat=True)) - object_types = ObjectType.objects.filter(pk__in=content_type_ids) + object_type_ids = set(queryset.values_list('object_type', flat=True)) + object_types = ObjectType.objects.filter(pk__in=object_type_ids) # Construct a Prefetch to pre-fetch only those related objects for which the # user has permission to view. @@ -152,11 +152,11 @@ class CachedValueSearchBackend(SearchBackend): params ) - # Iterate through each ContentType represented in the search results and prefetch any + # Iterate through each ObjectType represented in the search results and prefetch any # related objects necessary to render the prescribed display attributes (display_attrs). - for ct in object_types: - model = ct.model_class() - indexer = registry['search'].get(content_type_identifier(ct)) + for object_type in object_types: + model = object_type.model_class() + indexer = registry['search'].get(content_type_identifier(object_type)) if not (display_attrs := getattr(indexer, 'display_attrs', None)): continue @@ -170,7 +170,7 @@ class CachedValueSearchBackend(SearchBackend): # Compile a list of all CachedValues referencing this object type, and prefetch # any related objects if prefetch_fields: - objects = [r for r in results if r.object_type == ct] + objects = [r for r in results if r.object_type == object_type] prefetch_related_objects(objects, *prefetch_fields) # Omit any results pertaining to an object the user does not have permission to view diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py index f1f4e90dd..022059e51 100644 --- a/netbox/netbox/views/generic/bulk_views.py +++ b/netbox/netbox/views/generic/bulk_views.py @@ -4,7 +4,6 @@ from copy import deepcopy from django.contrib import messages from django.contrib.contenttypes.fields import GenericRel -from django.contrib.contenttypes.models import ContentType from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist, ValidationError from django.db import transaction, IntegrityError from django.db.models import ManyToManyField, ProtectedError, RestrictedError @@ -17,6 +16,7 @@ from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ from django_tables2.export import TableExport +from core.models import ObjectType from extras.models import ExportTemplate from extras.signals import clear_events from utilities.error_handlers import handle_protectederror @@ -124,7 +124,7 @@ class ObjectListView(BaseMultiObjectView, ActionsMixin, TableMixin): request: The current request """ model = self.queryset.model - content_type = ContentType.objects.get_for_model(model) + object_type = ObjectType.objects.get_for_model(model) if self.filterset: self.queryset = self.filterset(request.GET, self.queryset, request=request).qs @@ -143,7 +143,7 @@ class ObjectListView(BaseMultiObjectView, ActionsMixin, TableMixin): # Render an ExportTemplate elif request.GET['export']: - template = get_object_or_404(ExportTemplate, content_types=content_type, name=request.GET['export']) + template = get_object_or_404(ExportTemplate, object_types=object_type, name=request.GET['export']) return self.export_template(template, request) # Check for YAML export support on the model diff --git a/netbox/tenancy/tests/test_filtersets.py b/netbox/tenancy/tests/test_filtersets.py index 729dd7204..3bcbddd4b 100644 --- a/netbox/tenancy/tests/test_filtersets.py +++ b/netbox/tenancy/tests/test_filtersets.py @@ -1,6 +1,6 @@ -from django.contrib.contenttypes.models import ContentType from django.test import TestCase +from core.models import ObjectType from dcim.models import Manufacturer, Site from tenancy.filtersets import * from tenancy.models import * @@ -296,7 +296,7 @@ class ContactAssignmentTestCase(TestCase, ChangeLoggedFilterSetTests): ContactAssignment.objects.bulk_create(assignments) def test_object_type(self): - params = {'object_type_id': ContentType.objects.get_by_natural_key('dcim', 'site')} + params = {'object_type_id': ObjectType.objects.get_by_natural_key('dcim', 'site')} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) def test_contact(self): diff --git a/netbox/users/api/nested_serializers.py b/netbox/users/api/nested_serializers.py index 552c24906..2ab5d3aa5 100644 --- a/netbox/users/api/nested_serializers.py +++ b/netbox/users/api/nested_serializers.py @@ -1,9 +1,9 @@ from django.contrib.auth import get_user_model -from django.contrib.contenttypes.models import ContentType from drf_spectacular.utils import extend_schema_field from drf_spectacular.types import OpenApiTypes from rest_framework import serializers +from core.models import ObjectType from netbox.api.fields import ContentTypeField from netbox.api.serializers import WritableNestedSerializer from users.models import Group, ObjectPermission, Token @@ -49,7 +49,7 @@ class NestedTokenSerializer(WritableNestedSerializer): class NestedObjectPermissionSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='users-api:objectpermission-detail') object_types = ContentTypeField( - queryset=ContentType.objects.all(), + queryset=ObjectType.objects.all(), many=True ) groups = serializers.SerializerMethodField(read_only=True) diff --git a/netbox/users/tests/test_filtersets.py b/netbox/users/tests/test_filtersets.py index d42133d8d..5930285a9 100644 --- a/netbox/users/tests/test_filtersets.py +++ b/netbox/users/tests/test_filtersets.py @@ -1,7 +1,6 @@ import datetime from django.contrib.auth import get_user_model -from django.contrib.contenttypes.models import ContentType from django.test import TestCase from django.utils.timezone import make_aware @@ -199,7 +198,7 @@ class ObjectPermissionTestCase(TestCase, BaseFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_object_types(self): - object_types = ContentType.objects.filter(model__in=['site', 'rack']) + object_types = ObjectType.objects.filter(model__in=['site', 'rack']) params = {'object_types': [object_types[0].pk, object_types[1].pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/users/tests/test_views.py b/netbox/users/tests/test_views.py index 27d2aeab1..588730dbd 100644 --- a/netbox/users/tests/test_views.py +++ b/netbox/users/tests/test_views.py @@ -1,5 +1,4 @@ -from django.contrib.contenttypes.models import ContentType - +from core.models import ObjectType from users.models import * from utilities.testing import ViewTestCases, create_test_user @@ -115,7 +114,7 @@ class ObjectPermissionTestCase( @classmethod def setUpTestData(cls): - ct = ContentType.objects.get_by_natural_key('dcim', 'site') + object_type = ObjectType.objects.get_by_natural_key('dcim', 'site') permissions = ( ObjectPermission(name='Permission 1', actions=['view', 'add', 'delete']), @@ -127,7 +126,7 @@ class ObjectPermissionTestCase( cls.form_data = { 'name': 'Permission X', 'description': 'A new permission', - 'object_types': [ct.pk], + 'object_types': [object_type.pk], 'actions': 'view,edit,delete', } diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index aaee9679c..b71848411 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -1,16 +1,16 @@ import datetime import json -from urllib.parse import quote from typing import Dict, Any +from urllib.parse import quote from django import template from django.conf import settings -from django.contrib.contenttypes.models import ContentType from django.template.defaultfilters import date from django.urls import NoReverseMatch, reverse from django.utils import timezone from django.utils.safestring import mark_safe +from core.models import ObjectType from utilities.forms import get_selected_values, TableConfigForm from utilities.utils import get_viewname @@ -322,10 +322,10 @@ def applied_filters(context, model, form, query_params): save_link = None if user.has_perm('extras.add_savedfilter') and 'filter_id' not in context['request'].GET: - content_type = ContentType.objects.get_for_model(model).pk + object_type = ObjectType.objects.get_for_model(model).pk parameters = json.dumps(dict(context['request'].GET.lists())) url = reverse('extras:savedfilter_add') - save_link = f"{url}?content_types={content_type}¶meters={quote(parameters)}" + save_link = f"{url}?object_types={object_type}¶meters={quote(parameters)}" return { 'applied_filters': applied_filters, diff --git a/netbox/utilities/tests/test_counters.py b/netbox/utilities/tests/test_counters.py index 014c758e9..b87e73ace 100644 --- a/netbox/utilities/tests/test_counters.py +++ b/netbox/utilities/tests/test_counters.py @@ -1,11 +1,9 @@ -from django.contrib.contenttypes.models import ContentType from django.test import override_settings from django.urls import reverse from dcim.models import * -from users.models import ObjectPermission from utilities.testing.base import TestCase -from utilities.testing.utils import create_test_device, create_test_user +from utilities.testing.utils import create_test_device class CountersTest(TestCase):