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

Closes #17048: Replace all calls to get_user_model() with direct imports of User

Jeremy Stretch 1 год назад
Родитель
Сommit
c51e91dddd
37 измененных файлов с 79 добавлено и 132 удалено
  1. 3 3
      netbox/core/filtersets.py
  2. 3 3
      netbox/core/forms/filtersets.py
  3. 2 2
      netbox/core/management/commands/nbshell.py
  4. 3 3
      netbox/dcim/filtersets.py
  5. 2 4
      netbox/dcim/forms/bulk_edit.py
  6. 2 2
      netbox/dcim/forms/filtersets.py
  7. 2 4
      netbox/dcim/forms/model_forms.py
  8. 1 4
      netbox/dcim/tests/test_api.py
  9. 1 3
      netbox/dcim/tests/test_filtersets.py
  10. 1 3
      netbox/dcim/tests/test_views.py
  11. 2 2
      netbox/extras/api/serializers_/journaling.py
  12. 2 3
      netbox/extras/events.py
  13. 6 7
      netbox/extras/filtersets.py
  14. 3 4
      netbox/extras/forms/filtersets.py
  15. 1 4
      netbox/extras/management/commands/runscript.py
  16. 1 2
      netbox/extras/models/dashboard.py
  17. 1 2
      netbox/extras/models/staging.py
  18. 5 8
      netbox/netbox/authentication/__init__.py
  19. 1 5
      netbox/netbox/tests/test_authentication.py
  20. 3 4
      netbox/users/api/nested_serializers.py
  21. 3 3
      netbox/users/api/serializers_/users.py
  22. 2 3
      netbox/users/api/views.py
  23. 7 8
      netbox/users/filtersets.py
  24. 2 3
      netbox/users/forms/filtersets.py
  25. 4 4
      netbox/users/forms/model_forms.py
  26. 2 4
      netbox/users/graphql/filters.py
  27. 1 2
      netbox/users/graphql/schema.py
  28. 2 3
      netbox/users/graphql/types.py
  29. 1 2
      netbox/users/models/preferences.py
  30. 1 2
      netbox/users/models/tokens.py
  31. 1 5
      netbox/users/tests/test_api.py
  32. 1 4
      netbox/users/tests/test_filtersets.py
  33. 1 3
      netbox/users/tests/test_models.py
  34. 1 4
      netbox/users/tests/test_preferences.py
  35. 1 5
      netbox/utilities/testing/api.py
  36. 2 3
      netbox/utilities/testing/base.py
  37. 2 2
      netbox/utilities/testing/utils.py

+ 3 - 3
netbox/core/filtersets.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.contrib.contenttypes.models import ContentType
 from django.db.models import Q
 from django.utils.translation import gettext as _
@@ -7,6 +6,7 @@ import django_filters
 
 from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet
 from netbox.utils import get_data_backend_choices
+from users.models import User
 from utilities.filters import ContentTypeFilter
 from .choices import *
 from .models import *
@@ -141,12 +141,12 @@ class ObjectChangeFilterSet(BaseFilterSet):
         queryset=ContentType.objects.all()
     )
     user_id = django_filters.ModelMultipleChoiceFilter(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         label=_('User (ID)'),
     )
     user = django_filters.ModelMultipleChoiceFilter(
         field_name='user__username',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         to_field_name='username',
         label=_('User name'),
     )

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

@@ -1,5 +1,4 @@
 from django import forms
-from django.contrib.auth import get_user_model
 from django.utils.translation import gettext_lazy as _
 
 from core.choices import *
@@ -7,6 +6,7 @@ from core.models import *
 from netbox.forms import NetBoxModelFilterSetForm
 from netbox.forms.mixins import SavedFiltersMixin
 from netbox.utils import get_data_backend_choices
+from users.models import User
 from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
 from utilities.forms.fields import (
     ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField,
@@ -121,7 +121,7 @@ class JobFilterForm(SavedFiltersMixin, FilterForm):
         widget=DateTimePicker()
     )
     user = DynamicModelMultipleChoiceField(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         required=False,
         label=_('User')
     )
@@ -150,7 +150,7 @@ class ObjectChangeFilterForm(SavedFiltersMixin, FilterForm):
         required=False
     )
     user_id = DynamicModelMultipleChoiceField(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         required=False,
         label=_('User')
     )

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

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

+ 3 - 3
netbox/dcim/filtersets.py

@@ -1,5 +1,4 @@
 import django_filters
-from django.contrib.auth import get_user_model
 from django.contrib.contenttypes.models import ContentType
 from django.utils.translation import gettext as _
 from drf_spectacular.types import OpenApiTypes
@@ -16,6 +15,7 @@ from netbox.filtersets import (
 )
 from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
 from tenancy.models import *
+from users.models import User
 from utilities.filters import (
     ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
     NumericArrayFilter, TreeNodeMultipleChoiceFilter,
@@ -497,12 +497,12 @@ class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
         label=_('Location (slug)'),
     )
     user_id = django_filters.ModelMultipleChoiceFilter(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         label=_('User (ID)'),
     )
     user = django_filters.ModelMultipleChoiceFilter(
         field_name='user__username',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         to_field_name='username',
         label=_('User (name)'),
     )

+ 2 - 4
netbox/dcim/forms/bulk_edit.py

@@ -1,6 +1,5 @@
 from django import forms
 from django.conf import settings
-from django.contrib.auth import get_user_model
 from django.utils.translation import gettext_lazy as _
 from timezone_field import TimeZoneFormField
 
@@ -11,6 +10,7 @@ from extras.models import ConfigTemplate
 from ipam.models import ASN, VLAN, VLANGroup, VRF
 from netbox.forms import NetBoxModelBulkEditForm
 from tenancy.models import Tenant
+from users.models import User
 from utilities.forms import BulkEditForm, add_blank_choice, form_from_model
 from utilities.forms.fields import ColorField, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField
 from utilities.forms.rendering import FieldSet, InlineFields
@@ -459,9 +459,7 @@ class RackBulkEditForm(NetBoxModelBulkEditForm):
 class RackReservationBulkEditForm(NetBoxModelBulkEditForm):
     user = forms.ModelChoiceField(
         label=_('User'),
-        queryset=get_user_model().objects.order_by(
-            'username'
-        ),
+        queryset=User.objects.order_by('username'),
         required=False
     )
     tenant = DynamicModelChoiceField(

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

@@ -1,5 +1,4 @@
 from django import forms
-from django.contrib.auth import get_user_model
 from django.utils.translation import gettext_lazy as _
 
 from dcim.choices import *
@@ -10,6 +9,7 @@ from extras.models import ConfigTemplate
 from ipam.models import ASN, VRF
 from netbox.forms import NetBoxModelFilterSetForm
 from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
+from users.models import User
 from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
 from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField
 from utilities.forms.rendering import FieldSet
@@ -448,7 +448,7 @@ class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
         label=_('Rack')
     )
     user_id = DynamicModelMultipleChoiceField(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         required=False,
         label=_('User')
     )

+ 2 - 4
netbox/dcim/forms/model_forms.py

@@ -1,5 +1,4 @@
 from django import forms
-from django.contrib.auth import get_user_model
 from django.contrib.contenttypes.models import ContentType
 from django.utils.translation import gettext_lazy as _
 from timezone_field import TimeZoneFormField
@@ -11,6 +10,7 @@ from extras.models import ConfigTemplate
 from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VRF
 from netbox.forms import NetBoxModelForm
 from tenancy.forms import TenancyForm
+from users.models import User
 from utilities.forms import add_blank_choice, get_field_value
 from utilities.forms.fields import (
     CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField,
@@ -311,9 +311,7 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
     )
     user = forms.ModelChoiceField(
         label=_('User'),
-        queryset=get_user_model().objects.order_by(
-            'username'
-        )
+        queryset=User.objects.order_by('username')
     )
     comments = CommentField()
 

+ 1 - 4
netbox/dcim/tests/test_api.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.test import override_settings
 from django.urls import reverse
 from django.utils.translation import gettext as _
@@ -11,15 +10,13 @@ from extras.models import ConfigTemplate
 from ipam.models import ASN, RIR, VLAN, VRF
 from netbox.api.serializers import GenericObjectSerializer
 from tenancy.models import Tenant
+from users.models import User
 from utilities.testing import APITestCase, APIViewTestCases, create_test_device
 from virtualization.models import Cluster, ClusterType
 from wireless.choices import WirelessChannelChoices
 from wireless.models import WirelessLAN
 
 
-User = get_user_model()
-
-
 class AppTest(APITestCase):
 
     def test_root(self):

+ 1 - 3
netbox/dcim/tests/test_filtersets.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 
 from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
@@ -8,12 +7,11 @@ from dcim.models import *
 from ipam.models import ASN, IPAddress, RIR, VRF
 from netbox.choices import ColorChoices
 from tenancy.models import Tenant, TenantGroup
+from users.models import User
 from utilities.testing import ChangeLoggedFilterSetTests, create_test_device
 from virtualization.models import Cluster, ClusterType, ClusterGroup
 from wireless.choices import WirelessChannelChoices, WirelessRoleChoices
 
-User = get_user_model()
-
 
 class DeviceComponentFilterSetTests:
 

+ 1 - 3
netbox/dcim/tests/test_views.py

@@ -2,7 +2,6 @@ from decimal import Decimal
 from zoneinfo import ZoneInfo
 
 import yaml
-from django.contrib.auth import get_user_model
 from django.test import override_settings
 from django.urls import reverse
 from netaddr import EUI
@@ -13,11 +12,10 @@ from dcim.models import *
 from ipam.models import ASN, RIR, VLAN, VRF
 from netbox.choices import CSVDelimiterChoices, ImportFormatChoices
 from tenancy.models import Tenant
+from users.models import User
 from utilities.testing import ViewTestCases, create_tags, create_test_device, post_data
 from wireless.models import WirelessLAN
 
-User = get_user_model()
-
 
 class RegionTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
     model = Region

+ 2 - 2
netbox/extras/api/serializers_/journaling.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.core.exceptions import ObjectDoesNotExist
 from drf_spectacular.utils import extend_schema_field
 from rest_framework import serializers
@@ -8,6 +7,7 @@ from extras.choices import *
 from extras.models import JournalEntry
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.serializers import NetBoxModelSerializer
+from users.models import User
 from utilities.api import get_serializer_for_model
 
 __all__ = (
@@ -22,7 +22,7 @@ class JournalEntrySerializer(NetBoxModelSerializer):
     assigned_object = serializers.SerializerMethodField(read_only=True)
     created_by = serializers.PrimaryKeyRelatedField(
         allow_null=True,
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         required=False,
         default=serializers.CurrentUserDefault()
     )

+ 2 - 3
netbox/extras/events.py

@@ -1,9 +1,7 @@
-from collections import defaultdict
 import logging
 from collections import defaultdict
 
 from django.conf import settings
-from django.contrib.auth import get_user_model
 from django.contrib.contenttypes.models import ContentType
 from django.utils import timezone
 from django.utils.module_loading import import_string
@@ -14,6 +12,7 @@ from core.events import *
 from netbox.config import get_config
 from netbox.constants import RQ_QUEUE_DEFAULT
 from netbox.registry import registry
+from users.models import User
 from utilities.api import get_serializer_for_model
 from utilities.rqworker import get_rq_retry
 from utilities.serialization import serialize_object
@@ -83,7 +82,7 @@ def enqueue_event(queue, instance, user, request_id, event_type):
 
 
 def process_event_rules(event_rules, object_type, event_type, data, username=None, snapshots=None, request_id=None):
-    user = get_user_model().objects.get(username=username) if username else None
+    user = User.objects.get(username=username) if username else None
 
     for event_rule in event_rules:
 

+ 6 - 7
netbox/extras/filtersets.py

@@ -1,5 +1,4 @@
 import django_filters
-from django.contrib.auth import get_user_model
 from django.contrib.contenttypes.models import ContentType
 from django.db.models import Q
 from django.utils.translation import gettext as _
@@ -284,12 +283,12 @@ class SavedFilterFilterSet(ChangeLoggedModelFilterSet):
         field_name='object_types'
     )
     user_id = django_filters.ModelMultipleChoiceFilter(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         label=_('User (ID)'),
     )
     user = django_filters.ModelMultipleChoiceFilter(
         field_name='user__username',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         to_field_name='username',
         label=_('User (name)'),
     )
@@ -328,12 +327,12 @@ class BookmarkFilterSet(BaseFilterSet):
     object_type_id = MultiValueNumberFilter()
     object_type = ContentTypeFilter()
     user_id = django_filters.ModelMultipleChoiceFilter(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         label=_('User (ID)'),
     )
     user = django_filters.ModelMultipleChoiceFilter(
         field_name='user__username',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         to_field_name='username',
         label=_('User (name)'),
     )
@@ -410,12 +409,12 @@ class JournalEntryFilterSet(NetBoxModelFilterSet):
         queryset=ContentType.objects.all()
     )
     created_by_id = django_filters.ModelMultipleChoiceFilter(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         label=_('User (ID)'),
     )
     created_by = django_filters.ModelMultipleChoiceFilter(
         field_name='created_by__username',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         to_field_name='username',
         label=_('User (name)'),
     )

+ 3 - 4
netbox/extras/forms/filtersets.py

@@ -1,5 +1,4 @@
 from django import forms
-from django.contrib.auth import get_user_model
 from django.utils.translation import gettext_lazy as _
 
 from core.models import ObjectType, DataFile, DataSource
@@ -10,7 +9,7 @@ from netbox.events import get_event_type_choices
 from netbox.forms.base import NetBoxModelFilterSetForm
 from netbox.forms.mixins import SavedFiltersMixin
 from tenancy.models import Tenant, TenantGroup
-from users.models import Group
+from users.models import Group, User
 from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
 from utilities.forms.fields import (
     ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField,
@@ -453,7 +452,7 @@ class JournalEntryFilterForm(NetBoxModelFilterSetForm):
         widget=DateTimePicker()
     )
     created_by_id = DynamicModelMultipleChoiceField(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         required=False,
         label=_('User')
     )
@@ -472,7 +471,7 @@ class JournalEntryFilterForm(NetBoxModelFilterSetForm):
 
 class NotificationGroupFilterForm(SavedFiltersMixin, FilterForm):
     user_id = DynamicModelMultipleChoiceField(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         required=False,
         label=_('User')
     )

+ 1 - 4
netbox/extras/management/commands/runscript.py

@@ -3,12 +3,11 @@ import logging
 import sys
 import uuid
 
-from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand, CommandError
-from django.utils.module_loading import import_string
 
 from extras.jobs import ScriptJob
 from extras.scripts import get_module_and_script
+from users.models import User
 from utilities.request import NetBoxFakeRequest
 
 
@@ -28,8 +27,6 @@ class Command(BaseCommand):
         parser.add_argument('script', help="Script to run")
 
     def handle(self, *args, **options):
-        User = get_user_model()
-
         # Params
         script = options['script']
         loglevel = options['loglevel']

+ 1 - 2
netbox/extras/models/dashboard.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.db import models
 from django.utils.translation import gettext_lazy as _
 
@@ -11,7 +10,7 @@ __all__ = (
 
 class Dashboard(models.Model):
     user = models.OneToOneField(
-        to=get_user_model(),
+        to='users.User',
         on_delete=models.CASCADE,
         related_name='dashboard'
     )

+ 1 - 2
netbox/extras/models/staging.py

@@ -1,6 +1,5 @@
 import logging
 
-from django.contrib.auth import get_user_model
 from django.contrib.contenttypes.fields import GenericForeignKey
 from django.db import models, transaction
 from django.utils.translation import gettext_lazy as _
@@ -34,7 +33,7 @@ class Branch(ChangeLoggedModel):
         blank=True
     )
     user = models.ForeignKey(
-        to=get_user_model(),
+        to='users.User',
         on_delete=models.SET_NULL,
         blank=True,
         null=True

+ 5 - 8
netbox/netbox/authentication/__init__.py

@@ -2,7 +2,6 @@ import logging
 from collections import defaultdict
 
 from django.conf import settings
-from django.contrib.auth import get_user_model
 from django.contrib.auth.backends import ModelBackend, RemoteUserBackend as _RemoteUserBackend
 from django.contrib.auth.models import AnonymousUser
 from django.core.exceptions import ImproperlyConfigured
@@ -10,14 +9,12 @@ from django.db.models import Q
 from django.utils.translation import gettext_lazy as _
 
 from users.constants import CONSTRAINT_TOKEN_USER
-from users.models import Group, ObjectPermission
+from users.models import Group, ObjectPermission, User
 from utilities.permissions import (
     permission_is_exempt, qs_filter_from_constraints, resolve_permission, resolve_permission_type,
 )
 from .misc import _mirror_groups
 
-UserModel = get_user_model()
-
 AUTH_BACKEND_ATTRS = {
     # backend name: title, MDI icon name
     'amazon': ('Amazon AWS', 'aws'),
@@ -218,15 +215,15 @@ class RemoteUserBackend(_RemoteUserBackend):
         # instead we use get_or_create when creating unknown users since it has
         # built-in safeguards for multiple threads.
         if self.create_unknown_user:
-            user, created = UserModel._default_manager.get_or_create(**{
-                UserModel.USERNAME_FIELD: username
+            user, created = User._default_manager.get_or_create(**{
+                User.USERNAME_FIELD: username
             })
             if created:
                 user = self.configure_user(request, user)
         else:
             try:
-                user = UserModel._default_manager.get_by_natural_key(username)
-            except UserModel.DoesNotExist:
+                user = User._default_manager.get_by_natural_key(username)
+            except User.DoesNotExist:
                 pass
         if self.user_can_authenticate(user):
             if settings.REMOTE_AUTH_GROUP_SYNC_ENABLED:

+ 1 - 5
netbox/netbox/tests/test_authentication.py

@@ -1,7 +1,6 @@
 import datetime
 
 from django.conf import settings
-from django.contrib.auth import get_user_model
 from django.test import Client
 from django.test.utils import override_settings
 from django.urls import reverse
@@ -11,14 +10,11 @@ from rest_framework.test import APIClient
 from core.models import ObjectType
 from dcim.models import Site
 from ipam.models import Prefix
-from users.models import Group, ObjectPermission, Token
+from users.models import Group, ObjectPermission, Token, User
 from utilities.testing import TestCase
 from utilities.testing.api import APITestCase
 
 
-User = get_user_model()
-
-
 class TokenAuthenticationTestCase(APITestCase):
 
     @override_settings(LOGIN_REQUIRED=True, EXEMPT_VIEW_PERMISSIONS=['*'])

+ 3 - 4
netbox/users/api/nested_serializers.py

@@ -1,12 +1,11 @@
-from django.contrib.auth import get_user_model
-from drf_spectacular.utils import extend_schema_field
 from drf_spectacular.types import OpenApiTypes
+from drf_spectacular.utils import extend_schema_field
 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
+from users.models import Group, ObjectPermission, Token, User
 
 __all__ = [
     'NestedGroupSerializer',
@@ -26,7 +25,7 @@ class NestedGroupSerializer(WritableNestedSerializer):
 class NestedUserSerializer(WritableNestedSerializer):
 
     class Meta:
-        model = get_user_model()
+        model = User
         fields = ['id', 'url', 'display_url', 'display', 'username']
 
     @extend_schema_field(OpenApiTypes.STR)

+ 3 - 3
netbox/users/api/serializers_/users.py

@@ -1,11 +1,11 @@
-from django.contrib.auth import get_user_model, password_validation
+from django.contrib.auth import password_validation
 from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.utils import extend_schema_field
 from rest_framework import serializers
 
 from netbox.api.fields import SerializedPKRelatedField
 from netbox.api.serializers import ValidatedModelSerializer
-from users.models import Group, ObjectPermission
+from users.models import Group, ObjectPermission, User
 from .permissions import ObjectPermissionSerializer
 
 __all__ = (
@@ -49,7 +49,7 @@ class UserSerializer(ValidatedModelSerializer):
     )
 
     class Meta:
-        model = get_user_model()
+        model = User
         fields = (
             'id', 'url', 'display_url', 'display', 'username', 'password', 'first_name', 'last_name', 'email',
             'is_staff', 'is_active', 'date_joined', 'last_login', 'groups', 'permissions',

+ 2 - 3
netbox/users/api/views.py

@@ -1,6 +1,5 @@
 import logging
 
-from django.contrib.auth import get_user_model
 from django.db.models import Count
 from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.utils import extend_schema
@@ -13,7 +12,7 @@ from rest_framework.viewsets import ViewSet
 
 from netbox.api.viewsets import NetBoxModelViewSet
 from users import filtersets
-from users.models import Group, ObjectPermission, Token, UserConfig
+from users.models import Group, ObjectPermission, Token, User, UserConfig
 from utilities.data import deepmerge
 from utilities.querysets import RestrictedQuerySet
 from . import serializers
@@ -32,7 +31,7 @@ class UsersRootView(APIRootView):
 #
 
 class UserViewSet(NetBoxModelViewSet):
-    queryset = RestrictedQuerySet(model=get_user_model()).order_by('username')
+    queryset = RestrictedQuerySet(model=User).order_by('username')
     serializer_class = serializers.UserSerializer
     filterset_class = filtersets.UserFilterSet
 

+ 7 - 8
netbox/users/filtersets.py

@@ -1,13 +1,12 @@
 import django_filters
 
-from django.contrib.auth import get_user_model
 from django.db.models import Q
 from django.utils.translation import gettext as _
 
 from core.models import ObjectType
 from extras.models import NotificationGroup
 from netbox.filtersets import BaseFilterSet
-from users.models import Group, ObjectPermission, Token
+from users.models import Group, ObjectPermission, Token, User
 from utilities.filters import ContentTypeFilter
 
 __all__ = (
@@ -25,7 +24,7 @@ class GroupFilterSet(BaseFilterSet):
     )
     user_id = django_filters.ModelMultipleChoiceFilter(
         field_name='user',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         label=_('User (ID)'),
     )
     permission_id = django_filters.ModelMultipleChoiceFilter(
@@ -80,7 +79,7 @@ class UserFilterSet(BaseFilterSet):
     )
 
     class Meta:
-        model = get_user_model()
+        model = User
         fields = (
             'id', 'username', 'first_name', 'last_name', 'email', 'date_joined', 'last_login', 'is_staff', 'is_active',
             'is_superuser',
@@ -104,12 +103,12 @@ class TokenFilterSet(BaseFilterSet):
     )
     user_id = django_filters.ModelMultipleChoiceFilter(
         field_name='user',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         label=_('User'),
     )
     user = django_filters.ModelMultipleChoiceFilter(
         field_name='user__username',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         to_field_name='username',
         label=_('User (name)'),
     )
@@ -171,12 +170,12 @@ class ObjectPermissionFilterSet(BaseFilterSet):
     )
     user_id = django_filters.ModelMultipleChoiceFilter(
         field_name='users',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         label=_('User'),
     )
     user = django_filters.ModelMultipleChoiceFilter(
         field_name='users__username',
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         to_field_name='username',
         label=_('User (name)'),
     )

+ 2 - 3
netbox/users/forms/filtersets.py

@@ -1,5 +1,4 @@
 from django import forms
-from django.contrib.auth import get_user_model
 from django.utils.translation import gettext_lazy as _
 
 from netbox.forms import NetBoxModelFilterSetForm
@@ -80,7 +79,7 @@ class ObjectPermissionFilterForm(NetBoxModelFilterSetForm):
         label=_('Group')
     )
     user_id = DynamicModelMultipleChoiceField(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         required=False,
         label=_('User')
     )
@@ -121,7 +120,7 @@ class TokenFilterForm(SavedFiltersMixin, FilterForm):
         FieldSet('user_id', 'write_enabled', 'expires', 'last_used', name=_('Token')),
     )
     user_id = DynamicModelMultipleChoiceField(
-        queryset=get_user_model().objects.all(),
+        queryset=User.objects.all(),
         required=False,
         label=_('User')
     )

+ 4 - 4
netbox/users/forms/model_forms.py

@@ -1,6 +1,6 @@
 from django import forms
 from django.conf import settings
-from django.contrib.auth import get_user_model, password_validation
+from django.contrib.auth import password_validation
 from django.contrib.postgres.forms import SimpleArrayField
 from django.core.exceptions import FieldError
 from django.utils.safestring import mark_safe
@@ -152,7 +152,7 @@ class UserTokenForm(forms.ModelForm):
 
 class TokenForm(UserTokenForm):
     user = forms.ModelChoiceField(
-        queryset=get_user_model().objects.order_by('username'),
+        queryset=User.objects.order_by('username'),
         label=_('User')
     )
 
@@ -236,7 +236,7 @@ class GroupForm(forms.ModelForm):
     users = DynamicModelMultipleChoiceField(
         label=_('Users'),
         required=False,
-        queryset=get_user_model().objects.all()
+        queryset=User.objects.all()
     )
     object_permissions = DynamicModelMultipleChoiceField(
         required=False,
@@ -300,7 +300,7 @@ class ObjectPermissionForm(forms.ModelForm):
     users = DynamicModelMultipleChoiceField(
         label=_('Users'),
         required=False,
-        queryset=get_user_model().objects.all()
+        queryset=User.objects.all()
     )
     groups = DynamicModelMultipleChoiceField(
         label=_('Groups'),

+ 2 - 4
netbox/users/graphql/filters.py

@@ -1,9 +1,7 @@
-import strawberry
 import strawberry_django
-from django.contrib.auth import get_user_model
-from users import filtersets, models
 
 from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
+from users import filtersets, models
 
 __all__ = (
     'GroupFilter',
@@ -17,7 +15,7 @@ class GroupFilter(BaseFilterMixin):
     pass
 
 
-@strawberry_django.filter(get_user_model(), lookups=True)
+@strawberry_django.filter(models.User, lookups=True)
 @autotype_decorator(filtersets.UserFilterSet)
 class UserFilter(BaseFilterMixin):
     pass

+ 1 - 2
netbox/users/graphql/schema.py

@@ -1,9 +1,8 @@
 from typing import List
+
 import strawberry
 import strawberry_django
 
-from django.contrib.auth import get_user_model
-from django.contrib.auth.models import Group
 from users import models
 from .types import *
 

+ 2 - 3
netbox/users/graphql/types.py

@@ -1,10 +1,9 @@
 from typing import List
 
 import strawberry_django
-from django.contrib.auth import get_user_model
 
 from netbox.graphql.types import BaseObjectType
-from users.models import Group
+from users.models import Group, User
 from .filters import *
 
 __all__ = (
@@ -23,7 +22,7 @@ class GroupType(BaseObjectType):
 
 
 @strawberry_django.type(
-    get_user_model(),
+    User,
     fields=[
         'id', 'username', 'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'date_joined', 'groups',
     ],

+ 1 - 2
netbox/users/models/preferences.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.db import models
 from django.utils.translation import gettext_lazy as _
 
@@ -15,7 +14,7 @@ class UserConfig(models.Model):
     This model stores arbitrary user-specific preferences in a JSON data structure.
     """
     user = models.OneToOneField(
-        to=get_user_model(),
+        to='users.User',
         on_delete=models.CASCADE,
         related_name='config'
     )

+ 1 - 2
netbox/users/models/tokens.py

@@ -2,7 +2,6 @@ import binascii
 import os
 
 from django.conf import settings
-from django.contrib.auth import get_user_model
 from django.contrib.postgres.fields import ArrayField
 from django.core.validators import MinLengthValidator
 from django.db import models
@@ -25,7 +24,7 @@ class Token(models.Model):
     It also supports setting an expiration time and toggling write ability.
     """
     user = models.ForeignKey(
-        to=get_user_model(),
+        to='users.User',
         on_delete=models.CASCADE,
         related_name='tokens'
     )

+ 1 - 5
netbox/users/tests/test_api.py

@@ -1,16 +1,12 @@
-from django.contrib.auth import get_user_model
 from django.test import override_settings
 from django.urls import reverse
 
 from core.models import ObjectType
-from users.models import Group, ObjectPermission, Token
+from users.models import Group, ObjectPermission, Token, User
 from utilities.data import deepmerge
 from utilities.testing import APIViewTestCases, APITestCase, create_test_user
 
 
-User = get_user_model()
-
-
 class AppTest(APITestCase):
 
     def test_root(self):

+ 1 - 4
netbox/users/tests/test_filtersets.py

@@ -1,16 +1,13 @@
 import datetime
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils.timezone import make_aware
 
 from core.models import ObjectType
 from users import filtersets
-from users.models import Group, ObjectPermission, Token
+from users.models import Group, ObjectPermission, Token, User
 from utilities.testing import BaseFilterSetTests
 
-User = get_user_model()
-
 
 class UserTestCase(TestCase, BaseFilterSetTests):
     queryset = User.objects.all()

+ 1 - 3
netbox/users/tests/test_models.py

@@ -1,8 +1,6 @@
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 
-
-User = get_user_model()
+from users.models import User
 
 
 class UserConfigTest(TestCase):

+ 1 - 4
netbox/users/tests/test_preferences.py

@@ -1,10 +1,10 @@
-from django.contrib.auth import get_user_model
 from django.test import override_settings
 from django.test.client import RequestFactory
 from django.urls import reverse
 
 from dcim.models import Site
 from dcim.tables import SiteTable
+from users.models import User
 from users.preferences import UserPreference
 from utilities.testing import TestCase
 
@@ -16,9 +16,6 @@ DEFAULT_USER_PREFERENCES = {
 }
 
 
-User = get_user_model()
-
-
 class UserPreferencesTest(TestCase):
     user_permissions = ['dcim.view_site']
 

+ 1 - 5
netbox/utilities/testing/api.py

@@ -3,7 +3,6 @@ import json
 
 import strawberry_django
 from django.conf import settings
-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
@@ -16,7 +15,7 @@ from strawberry.types.union import StrawberryUnion
 from core.choices import ObjectChangeActionChoices
 from core.models import ObjectChange, ObjectType
 from ipam.graphql.types import IPAddressFamilyType
-from users.models import ObjectPermission, Token
+from users.models import ObjectPermission, Token, User
 from utilities.api import get_graphql_type_for_model
 from .base import ModelTestCase
 from .utils import disable_warnings
@@ -27,9 +26,6 @@ __all__ = (
 )
 
 
-User = get_user_model()
-
-
 #
 # REST/GraphQL API Tests
 #

+ 2 - 3
netbox/utilities/testing/base.py

@@ -1,6 +1,5 @@
 import json
 
-from django.contrib.auth import get_user_model
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.postgres.fields import ArrayField, RangeField
 from django.core.exceptions import FieldDoesNotExist
@@ -11,7 +10,7 @@ from netaddr import IPNetwork
 from taggit.managers import TaggableManager
 
 from core.models import ObjectType
-from users.models import ObjectPermission
+from users.models import ObjectPermission, User
 from utilities.data import ranges_to_string
 from utilities.object_types import object_type_identifier
 from utilities.permissions import resolve_permission_type
@@ -29,7 +28,7 @@ class TestCase(_TestCase):
     def setUp(self):
 
         # Create the test user and assign permissions
-        self.user = get_user_model().objects.create_user(username='testuser')
+        self.user = User.objects.create_user(username='testuser')
         self.add_permissions(*self.user_permissions)
 
         # Initialize the test client

+ 2 - 2
netbox/utilities/testing/utils.py

@@ -3,7 +3,6 @@ import logging
 import re
 from contextlib import contextmanager
 
-from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Permission
 from django.utils.text import slugify
 
@@ -11,6 +10,7 @@ from core.models import ObjectType
 from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
 from extras.choices import CustomFieldTypeChoices
 from extras.models import CustomField, Tag
+from users.models import User
 from virtualization.models import Cluster, ClusterType, VirtualMachine
 
 
@@ -67,7 +67,7 @@ def create_test_user(username='testuser', permissions=None):
     """
     Create a User with the given permissions.
     """
-    user = get_user_model().objects.create_user(username=username)
+    user = User.objects.create_user(username=username)
     if permissions is None:
         permissions = ()
     for perm_name in permissions: