Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions rest_framework/authtoken/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ def url_for_result(self, result):

class TokenAdmin(admin.ModelAdmin):
list_display = ('key', 'user', 'created')
list_filter = ('created',)
fields = ('user',)
search_fields = ('user__username',)
search_fields = ('user__%s' % User.USERNAME_FIELD,)
search_help_text = _('Username')
ordering = ('-created',)
ordering = ('user__%s' % User.USERNAME_FIELD,)
Comment on lines +28 to +30
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes to use USERNAME_FIELD instead of hardcoded 'username' lack test coverage. Consider adding tests that verify the admin configuration works correctly with a custom user model that uses a different USERNAME_FIELD (e.g., 'email'), ensuring search and ordering function as expected.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@m000 it would be great to add test coverage for the changes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. It took a while to figure it out. Admin tests are a major PITA because modules include code that runs on load.

actions = None # Actions not compatible with mapped IDs.

def get_changelist(self, request, **kwargs):
Expand Down
26 changes: 25 additions & 1 deletion tests/test_authtoken.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import importlib
from io import StringIO
from unittest.mock import patch

import pytest
from django.contrib.admin import site
Expand All @@ -11,7 +12,7 @@
from rest_framework.authtoken.admin import TokenAdmin
from rest_framework.authtoken.management.commands.drf_create_token import \
Command as AuthTokenCommand
from rest_framework.authtoken.models import Token
from rest_framework.authtoken.models import Token, TokenProxy
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.exceptions import ValidationError

Expand All @@ -36,6 +37,29 @@ def test_model_admin_displayed_fields(self):
token_admin = TokenAdmin(self.token, self.site)
assert token_admin.get_fields(mock_request) == ('user',)

@patch('django.contrib.admin.site.register') # avoid duplicate registrations
def test_model_admin__username_field(self, mock_register):
import rest_framework.authtoken.admin as authtoken_admin_m

class EmailUser(User):
USERNAME_FIELD = 'email'
username = None

for user_model in (User, EmailUser):
with (
self.subTest(user_model=user_model),
patch('django.contrib.auth.get_user_model', return_value=user_model) as get_user_model
):
importlib.reload(authtoken_admin_m) # reload after patching
assert get_user_model.call_count == 1

mock_request = object()
token_admin = authtoken_admin_m.TokenAdmin(TokenProxy, self.site)
assert token_admin.get_search_fields(mock_request) == (f'user__{user_model.USERNAME_FIELD}',)
assert token_admin.get_ordering(mock_request) == (f'user__{user_model.USERNAME_FIELD}',)

importlib.reload(authtoken_admin_m) # restore after testing

def test_token_string_representation(self):
assert str(self.token) == 'test token'

Expand Down