I am using DRF for Token authentication as: while a user login, i am creating a token and for every user request Django is hitting database (for verifying token and get user info). So i want to cache the tokens of currently logged IN users into my Redis cache (running on same server). So that i can avoid a lot of Database hits and my request/response cycle will be faster.
I am new to django and got struct to implement this. Please help me with code or should i change from tokenbased to session based authentication?.
(My frontend is mobile app, So i should use token based auth only.)
I am currently using DRF token based authentication for every view as:-
@api_view(['GET','POST'])
@permission_classes([IsAuthenticated]) #checks for token and gets the user object
def Test_view(request):
#some db queries
Return Response({'test':'returned'})
created login view as follows:-
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate
@api_view(['POST'])
@permission_classes([AllowAny])
def UserLogin(request):
if request.method=='POST':
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key,'name':user.fname+' '+user.lname,
'phone':user.phone,'username':user.username,'email':user.email})
else:
return Response({'error': 'Invalid credentials'})
in my settings.py:-
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES' : (
'rest_framework.authentication.TokenAuthentication',
),
}
and i am currently using redis cache:-
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': "redis://127.0.0.1:6379",
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'IGNORE_EXCEPTIONS': True,
},
'TIMEOUT': None,
}
}
If you want stateless auth that will not affect your database in the long run, consider JWT
.
Install simplejwt
:
pip install djangorestframework-simplejwt
Use JWTStatelessUserAuthentication
:
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework_simplejwt.authentication.JWTStatelessUserAuthentication',
)
...
}
Generate token:
from django.contrib.auth import authenticate
from rest_framework_simplejwt.tokens import RefreshToken
def get_tokens_for_user(user):
refreshToken = RefreshToken.for_user(user)
return {
'accessToken': str(refreshToken.access_token),
'refreshToken': str(refreshToken)
}
@api_view(['POST'])
@permission_classes([AllowAny])
def UserLogin(request):
if request.method=='POST':
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
tokens = get_tokens_for_user(user)
return Response(
tokens | {
'name': f"{user.fname} {user.lname}",
'phone': user.phone,
'username': user.username,
'email': user.email
}
)
else:
return Response({'error': 'Invalid credentials'})
Reference: simplejwt.