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:
- The Token model isn't properly registered with Django's ORM
- The
objectsmanager (which handles database queries) isn't available - 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:
- Add
'rest_framework.authtoken'toINSTALLED_APPSin settings.py - Run
python manage.py migrateto create the token table - 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.