Skip to content

Instantly share code, notes, and snippets.

@AndrewPix
Last active January 3, 2024 14:23
Show Gist options
  • Save AndrewPix/cdd9276b1d5683459b965d5cc4517b26 to your computer and use it in GitHub Desktop.
Save AndrewPix/cdd9276b1d5683459b965d5cc4517b26 to your computer and use it in GitHub Desktop.
Integrate django-rest-knox with django-rest-auth
from rest_framework import serializers
from rest_auth.serializers import UserDetailsSerializer
class KnoxSerializer(serializers.Serializer):
"""
Serializer for Knox authentication.
"""
token = serializers.CharField()
user = UserDetailsSerializer()
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend',
)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication',),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
}
REST_AUTH_TOKEN_MODEL = 'knox.models.AuthToken'
REST_AUTH_TOKEN_CREATOR = 'project.apps.accounts.utils.create_knox_token'
REST_AUTH_SERIALIZERS = {
'USER_DETAILS_SERIALIZER': 'project.apps.accounts.serializers.UserDetailsSerializer',
'TOKEN_SERIALIZER': 'project.apps.accounts.serializers.KnoxSerializer',
}
from knox.models import AuthToken
def create_knox_token(token_model, user, serializer):
token = AuthToken.objects.create(user=user)
return token
from rest_framework.response import Response
from rest_auth.views import LoginView
from rest_auth.registration.views import RegisterView
from allauth.account.utils import complete_signup
from allauth.account import app_settings as allauth_settings
from .serializers import KnoxSerializer
from .utils import create_knox_token
class KnoxLoginView(LoginView):
def get_response(self):
serializer_class = self.get_response_serializer()
data = {
'user': self.user,
'token': self.token
}
serializer = serializer_class(instance=data, context={'request': self.request})
return Response(serializer.data, status=200)
class KnoxRegisterView(RegisterView):
def get_response_data(self, user):
return KnoxSerializer({'user': user, 'token': self.token}).data
def perform_create(self, serializer):
user = serializer.save(self.request)
self.token = create_knox_token(None, user, None)
complete_signup(self.request._request, user, allauth_settings.EMAIL_VERIFICATION, None)
return user
@BhuwanPandey
Copy link

BhuwanPandey commented Aug 22, 2022

This is brilliant! Thanks.

One question,

I'm using dj-rest-auth, an extension of django-rest-auth, and I've tried to integrate django-rest-knox with it in your code.

2020-08-28_04h40_14

I then POST the API to try and register with the URL http://127.0.0.1:8000/dj-rest-auth/registration/ and the result was that the token was stored in the AuthToken model and at the same time the User model (which is not the Django standard but, CustomUserModel. ) has also saved the user's record .

However, an

"AttributeError at /dj-rest-auth/registration/
'CustomUser' object has no attribute 'auth_token'" 

error.

I thought it was because the User model does not have an auth_token field, so I tried to migrate it again.

But as a result I get the error "users.CustomUser.auth_token: (models.E006) The field 'auth_token' clashes with the field 'auth_token' " from model 'users.customuser'.

I can't figure out why I'm getting an

"AttributeError at /dj-rest-auth/registration/
'CustomUser' object has no attribute 'auth_token'"

errorr .

Could you please advise me on how to resolve this? I can attach the code such as models.py separately if needed.

I'm Japanese, I'm not very good at English and I don't have much programming experience. Feel free to tell me if there is something difficult to understand in your question.

Main reason behind this is that,
When you are using dj_rest_auth registration method
In RegisterView there is method called get_response_data(self, user) which
return TokenSerializer(user.auth_token, context=self.get_serializer_context()).data

Here user.auth_token is main cause of errors raises
when you look on AuthToken in knox.models ,you found
user = models.ForeignKey(User, null=False, blank=False,
related_name='auth_token_set', on_delete=models.CASCADE)
whose related_name is auth_token_set not auth_token

Solution for this is,
1.Try to use custom register view as mention above
or change the auth_token to auth_token_set by overriding the
get_response_data(self, user) method of dj_rest_auth.registration.views.registerview

Hope you got it..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment