DRF seemingly not migrating the Auth Token Model

Hello everyone, this problem has thrown me for a doozy for a few days now, and I’m hoping ya’ll might see something I’ve missed.

The issue:
When I make an API request towards one of my endpoints (let’s say /api/users) when using Token Authentication, I receive the following error.

    except model.DoesNotExist:
AttributeError: type object 'Token' has no attribute 'DoesNotExist'

and

    token = model.objects.select_related('user').get(key=key)
AttributeError: type object 'Token' has no attribute 'objects'

From my research thus far, it appears that Django is unaware of the authtoken model existing, therefore it can’t evaluate. Other people facing this issue say to just put it in the INSTALLED_APPS in settings.py and migrate. Well, that’s where things get weird.

Here is a snippet of my settings.py

INSTALLED_APPS = [
...
    'django.contrib.postgres',
    'rest_framework',
    'rest_framework.authtoken',
    'django_summernote',
...
]

and when running python manage.py migrate, I get the following error.
No migrations to apply.
It should be noted I get the same error when running python manage.py migrate rest_framework

This led me to believe that the migrations had already occured, but when checking the database, there is no “authtoken” table nor an entry in the django_migrations table.

I have tried uninstalling and reinstalling djangorestframework, running every variety of makemigrations and migrate, and more. If anyone has any suggestions, it would be greatly appreciated.

Thanks!

What is the output of showmigrations?

We’re going to need to see more of the view and code being executed here. You’re not showing enough to allow us to diagnose the issue.

Also, it’s more helpful if you post the complete error message with the full traceback.

Hello, this is the output I get on showmigrations

admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
 [X] 0004_auto_20241016_1640
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
 [X] 0008_alter_user_username_max_length
 [X] 0009_alter_user_last_name_max_length
 [X] 0010_alter_group_name_max_length
 [X] 0011_update_proxy_permissions
 [X] 0012_alter_user_first_name_max_length
 [X] 0013_auto_20241016_1639
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
django_summernote
 [X] 0001_initial
 [X] 0002_update-help_text
sessions
 [X] 0001_initial
 [X] 0002_auto_20241016_1640

Hi Ken, thanks for your response. Here is the src.

views.py:

class UserViewSet(viewsets.ModelViewSet):
    """
    List all users for either the company of current authenticated user or for a requested group.
    Example: /api/v1/users/ or /api/v1/users/?group_id=5
    """

    serializer_class = UserSerializer
    authentication_classes = [TokenAuthentication, SessionAuthentication]
    permission_classes = [PermissionsCheck]

    def get_queryset(self):
        group_id = self.request.query_params.get('group_id', None)
        user = self.request.user
        if group_id:
            return User.objects.select_related("groupmember").filter(group_id=user.current_group_id)
        else:
            return user.get_company_members()

permissions.py

class PermissionsCheck(permissions.BasePermission):
    """
    Checks supervisor and superuser perms
    """
    def has_permission(self, request, view):
        user = request.user
        if user :
            return user.is_supervisor() or user.is_superuser()
        else:
            return False

Here is the full error log:

Internal Server Error: /api/users/
Traceback (most recent call last):
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\authentication.py", line 201, in authenticate_credentials
    token = model.objects.select_related('user').get(key=key)
AttributeError: type object 'Token' has no attribute 'objects'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\request.py", line 74, in wrap_attributeerrors
    yield
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\request.py", line 231, in user     
    self._authenticate()
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\request.py", line 384, in _authenticate
    user_auth_tuple = authenticator.authenticate(self)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\authentication.py", line 196, in authenticate
    return self.authenticate_credentials(token)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\authentication.py", line 202, in authenticate_credentials
    except model.DoesNotExist:
AttributeError: type object 'Token' has no attribute 'DoesNotExist'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\django\views\decorators\csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\viewsets.py", line 124, in view    
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 509, in dispatch   
    response = self.handle_exception(exc)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 497, in dispatch   
    self.initial(request, *args, **kwargs)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 414, in initial    
    self.perform_authentication(request)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 324, in perform_authentication
    request.user
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\request.py", line 230, in user     
    with wrap_attributeerrors():
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\contextlib.py", line 153, in __exit__
    self.gen.throw(typ, value, traceback)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\request.py", line 78, in wrap_attributeerrors
    raise exc.with_traceback(info[2])
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\request.py", line 74, in wrap_attributeerrors
    yield
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\request.py", line 231, in user     
    self._authenticate()
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\request.py", line 384, in _authenticate
    user_auth_tuple = authenticator.authenticate(self)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\authentication.py", line 196, in authenticate
    return self.authenticate_credentials(token)
  File "C:\Users\mthomas\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\authentication.py", line 202, in authenticate_credentials
    except model.DoesNotExist:
rest_framework.request.WrappedAttributeError: type object 'Token' has no attribute 'DoesNotExist'

It should also be noted that session based authentication works fine, and I am able to access the endpoint from the web interface.

Thanks!

It should include a section for the auth token app.

authtoken
 [ ] 0001_initial
 [ ] 0002_auto_20160226_1747
 [ ] 0003_tokenproxy
 [ ] 0004_alter_tokenproxy_options

It seems likely that for some reason, rest_framework.authtoken is not in the INSTALLED_APPS setting as you expect. When I remove this app from my settings, I end up with:

In [1]: from rest_framework.authtoken.models import Token

In [2]: Token.DoesNotExist
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[2], line 1
----> 1 Token.DoesNotExist

AttributeError: type object 'Token' has no attribute 'DoesNotExist'

When the app is included in the settings, it works:

In [1]: from rest_framework.authtoken.models import Token

In [2]: Token.DoesNotExist
Out[2]: rest_framework.authtoken.models.Token.DoesNotExist
  1. is there a configuration error and rest_framework.authtoken isn’t actually in INSTALLED_APPS as you’d expect? ie, it’s running another settings module or the value is dynamic.
  2. can you open a shell and try and import Token (like in my snippets above) and access Token.DoesNotExist, and print your INSTALLED_APPS, and share the results?

Running the import in the shell yielded the same results, but it was not in installed apps correctly. I had the project opened in VSCode, where the search pallete had decided to use the settings.py from a different project, so my edits were not affecting it. After editing the correct settings.py, everything worked as expected… Thank ya’ll for the help

1 Like