}

Fix: AttributeError - Token Has No Attribute 'objects' [Django REST Framework]

The Error: Token Has No Attribute 'objects'

When implementing token-based authentication in Django REST Framework (DRF), you might encounter this confusing error:

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

This typically happens when using ObtainAuthToken or manually creating tokens with Token.objects.get_or_create().

Full Error Traceback

Here's what the complete error looks like:

Traceback (most recent call last):
  File "/opt/project/user/tests/test_user_api.py", line 76, in test_create_token_for_user
    res = self.client.post(reverse('user:token'), payload)
  ...
  File "/usr/local/lib/python3.7/site-packages/rest_framework/authtoken/views.py", line 46, in post
    token, created = Token.objects.get_or_create(user=user)
AttributeError: type object 'Token' has no attribute 'objects'

Why Does This Error Occur?

The error occurs because Django REST Framework's Token model requires the rest_framework.authtoken app to be installed and its database migrations to be run. Without this:

  1. The Token model isn't properly registered with Django's ORM
  2. The objects manager (which handles database queries) isn't available
  3. Any attempt to query tokens will fail

The Solution

Step 1: Add authtoken to INSTALLED_APPS

Open your settings.py and add 'rest_framework.authtoken' to your INSTALLED_APPS:

# settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Third-party apps
    'rest_framework',
    'rest_framework.authtoken',  # Add this line!

    # Your apps
    'your_app',
]

Step 2: Run Migrations

After adding the app, create and apply the database migrations:

python manage.py migrate

This creates the authtoken_token table in your database.

Step 3: Verify the Fix

Test that tokens work correctly:

from rest_framework.authtoken.models import Token
from django.contrib.auth import get_user_model

User = get_user_model()
user = User.objects.first()

# This should now work without errors
token, created = Token.objects.get_or_create(user=user)
print(f"Token: {token.key}")

Complete Token Authentication Setup

Here's a complete example of setting up token authentication in DRF:

settings.py

INSTALLED_APPS = [
    # ... other apps
    'rest_framework',
    'rest_framework.authtoken',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
}

urls.py

from django.urls import path
from rest_framework.authtoken.views import obtain_auth_token

urlpatterns = [
    # ... other urls
    path('api/token/', obtain_auth_token, name='api_token_auth'),
]

Using the Token Endpoint

Request a token:

curl -X POST http://localhost:8000/api/token/ \
     -H "Content-Type: application/json" \
     -d '{"username": "myuser", "password": "mypassword"}'

Response:

{"token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"}

Using the Token in Requests

Include the token in the Authorization header:

curl -X GET http://localhost:8000/api/protected-endpoint/ \
     -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"

Creating Tokens Programmatically

In Views

from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.views import APIView

class CreateTokenView(APIView):
    def post(self, request):
        user = request.user
        token, created = Token.objects.get_or_create(user=user)
        return Response({'token': token.key})

In Signals (Auto-create on User Registration)

# signals.py
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

Don't forget to import the signals in your app's apps.py:

# apps.py
from django.apps import AppConfig

class YourAppConfig(AppConfig):
    name = 'your_app'

    def ready(self):
        import your_app.signals  # noqa

Common Related Issues

Token Already Exists

If you try to create a token for a user who already has one:

# Use get_or_create to avoid IntegrityError
token, created = Token.objects.get_or_create(user=user)

Regenerate Token

To create a new token for a user:

from rest_framework.authtoken.models import Token

# Delete old token
Token.objects.filter(user=user).delete()

# Create new one
new_token = Token.objects.create(user=user)

Custom Token Model

If you need additional fields on your token:

# models.py
from rest_framework.authtoken.models import Token

class CustomToken(Token):
    # Token inherits key, user, created fields
    expires_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        proxy = True  # Or set to False for a separate table

Summary

The AttributeError: type object 'Token' has no attribute 'objects' error is caused by a missing app registration. To fix it:

  1. Add 'rest_framework.authtoken' to INSTALLED_APPS in settings.py
  2. Run python manage.py migrate to create the token table
  3. Verify by testing Token.objects.get_or_create(user=user)

This is a common gotcha when setting up Django REST Framework token authentication for the first time.