-
-
Save AndrewPix/cdd9276b1d5683459b965d5cc4517b26 to your computer and use it in GitHub Desktop.
| 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 |
Love this and it's working fine except for one thing. After logging in, the expiry date is not included in the response.
urls.py
path('api/v1/', include("api.urls")),
path('api/v1/login/', KnoxLoginView.as_view(), name='knox_login'),
path('api-auth/', include('rest_framework.urls')),
path('api/v1/dj-rest-auth/', include('dj_rest_auth.urls')),
views.py
from dj_rest_auth.views import LoginView
class KnoxLoginView(LoginView):
def get_response(self):
serializer_class = self.get_response_serializer()
print(self)
data = {
'user': self.user,
'token': self.token
}
serializer = serializer_class(instance=data, context={'request': self.request})
return Response(serializer.data, status=200)
settings.py
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication',),
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}
REST_AUTH_TOKEN_MODEL = 'knox.models.AuthToken'
REST_AUTH_TOKEN_CREATOR = 'api.utils.create_knox_token'
REST_AUTH_SERIALIZERS = {
'USER_DETAILS_SERIALIZER': 'api.serializers.UserDetailsSerializer',
'TOKEN_SERIALIZER': 'api.serializers.KnoxSerializer',
}
from rest_framework.settings import api_settings
REST_KNOX = {
'TOKEN_TTL': timedelta(minutes=1),
'TOKEN_LIMIT_PER_USER': None,
'AUTO_REFRESH': False,
'EXPIRY_DATETIME_FORMAT': api_settings.DATETIME_FORMAT
}
api.utils
from knox.models import AuthToken
def create_knox_token(token_model, user, serializer):
token = AuthToken.objects.create(user=user)
return token
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.
![]()
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..

make sure that you have the correct urlpattern order and that you have added the KnoxLoginView in the urlpattern. I changed the urlpattern to the following:
Hope this helps!
P.S.: make sure that you change your code to what it was when you got the attribute error..