To get started, make sure you have django installed by using the command pipenv install django
in your terminal. (Make sure you are in a virtual environment: pipenv shell
)
Create a project django-admin startproject <project-name>
. For this example, I will be creating a project about tvshows! So, my command will be django-admin startproject tvshows
.
Now, cd into your project and make sure manage.py
is in your root directory.
The command python manage.py runserver
allows your app to be up and running. http://127.0.0.1:8000/
on your browser, should show this:
Next, create a superuser:python manage.py createsuperuser
This asks for a username, password and email address. Now that you have created a superuser, on the browser, add /admin
to your initial site like this: http://127.0.0.1:8000/admin
and your browser should show:
Use the username and password used to create the superuser to login! you should then see:
Now, you are ready to create user auth using knox where a token is generated for a user to login and access data.
You need to install the following:
pipenv install djangorestframework
pipenv install django-rest-knox
In settings.py
, add:
INSTALLED_APPS = [
...
'rest_framework',
'knox'
]
Now, let's create an app for our project.
Use python manage.py startapp <name>
in the terminal. For now, I've used python manage.py startapp backend
.
Your files in your code editor should look something like this:
Starting with Registration API:
In the backend
folder, create a new file and name it serializers.py
and add:
from rest_framework import serializers
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
class CreateUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User.objects.create_user(validated_data['username'],
None,
validated_data['password'])
return user
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username')
Then, create an api.py
file in the backend
folder and add:
from rest_framework import viewsets, permissions, generics
from rest_framework.response import Response
from knox.models import AuthToken
from .serializers import CreateUserSerializer, UserSerializer
class RegistrationAPI(generics.GenericAPIView):
serializer_class = CreateUserSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
Now, to add the endpoints, create a urls.py
file in the backend
folder and add:
from django.urls import path
from .api import RegistrationAPI
from knox import views as knox_views
urlpatterns = [
path('register/', RegistrationAPI.as_view()),
]
You also need to add endpoint in urls.py
file in the project folder which is tvshows
in this case:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('backend.urls')),
path('api/auth/', include('knox.urls'))
]
Registration API is now complete. Next is creating a Login API.
In the serializers.py
in your backend
folder, add:
class LoginUserSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
def validate(self, data):
user = authenticate(**data)
if user and user.is_active:
return user
raise serializers.ValidationError("Invalid Details.")
Next, in api.py
add:
from .serializers import CreateUserSerializer, UserSerializer, LoginUserSerializer
class LoginAPI(generics.GenericAPIView):
serializer_class = LoginUserSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
You need to add the endpoints in urls.py
in the backend
folder:
from .api import RegistrationAPI, LoginAPI
urlpatterns = [
...,
path('login/', LoginAPI.as_view()),
]
Finally, you need an API to shows the user data when the user successfully logs in. To do this, you need to create a class in api.py
file in your backend
folder:
class UserAPI(generics.RetrieveAPIView):
permission_classes = [permissions.IsAuthenticated, ]
serializer_class = UserSerializer
def get_object(self):
return self.request.user
This needs an endpoint too. Therefore, in your urls.py
in your backend
folder, add:
from django.urls import path
from .api import RegistrationAPI, LoginAPI, UserAPI
from knox import views as knox_views
urlpatterns = [
path('register/', RegistrationAPI.as_view()),
path('login/', LoginAPI.as_view()),
path('user/', UserAPI.as_view()),
]
Now, you're all set. Make sure you run those migrations, using python manage.py makemigrations
followed by python manage.py migrate
.
You can use Postman to check if your endpoint work and you're able to do GET
and POST
requests.
Let's start with registration. You need to add header
and a body
to create a new user. So using the url http://127.0.0.1:8000/api/register/
, add key Content-Type
and value application/json
on the header
like this:
And add the body
to POST
to the API, like this:
Your registration has been successful!
You can now log in using http://127.0.0.1:8000/api/login/
and POST method
adding the same body
used to register. This generates a token:
You cannot access the user details without passing the token that was generated when successfully logging in, as seen below:
You are unable to view the user detail.
Therefore, you need to pass the token like this:
You are now able to view the user detail:
You can also see if the user was successfully created on django admin:
bhuma08
was the superuser I created at the beginning and user1
was created using Postman.
For logout functionality, just add a path in your backend/urls.py
:
urlpatterns = [
...
path('logout/', knox_views.LogoutView.as_view(), name='knox_logout')
]
That's the end! :)
Top comments (9)
One problem i am having is that for every login session , knox is creating a new token and this is making my every api to get slow , because now every api is taking lot of time from 600k token entries to identify the one needed for current session.
Is there a way to assign one token with one user , so that this multiple token to one user probelm can get solved.
Also i want that concurrenly multiple user can login with same credentials
Great post. For some reason I can't get the token in / user /. Any ideas?
in your project settings.py file add
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication',)
}
Thank you. The user endpoint will not work as expected if you don't include this in your settings.py file
token is created in model AuthToken. /user/ from UserAPI , shows only your response is from User model.
Anyway, if you try to get it from AuthToken, you need to decrypt it.
Thank You so much for writing this article
very nice and short !!!!
how do you get the token expirering date ?
While i trying to logout using knox logout url it shows response like this..How to solve..?
{
"detail": "Authentication credentials were not provided."
}