Suppose I have a self-made User Model which holds username and password field. Now I want to login with my self-made username and password in Django. How can I do that? Besides I need to build a Login Api using this username and password. How to do that?
1 Answer
I can implement the simple login system like the following.
TokenAuthentication can be used in the DRF by adding some configs in settings.py file.
# REST framework
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication'
]
}
Now create the users app by executing the following command.
python manage.py startapp users
And I can create the custom user model in the models.py. Let's say that the app name is "users" and the model name is "Account". You need to set the AUTH_USER_MODEL in settings.py.
# Application definition
INSTALLED_APPS = [
...
'rest_framework',
'corsheaders',
'users',
'rest_framework.authtoken'
]
# specify user model
AUTH_USER_MODEL = 'users.Account'
In models.py of the users app, I can define the user model by deriving from the AbstractBaseUser.
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, UserManager
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
class Account(AbstractBaseUser):
"""
A model for users
It simply has the three fields `username`, `password`, `last_login`.
In addition, it has several shifts.
"""
username = models.CharField(max_length=50, unique=True)
USERNAME_FIELD = 'username'
objects = UserManager()
@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)
In serializers.py, you can set the password field as write-only.
from attr import fields
from rest_framework import serializers
from .models import Account
class AccountSerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
model = Account
extra_kwargs = {
'password': {'write_only': True}
}
Finally, in urls.py of the users app, login can be implemented using rest_framework.authtoken
from django.urls import path
from rest_framework.authtoken import views
from .views import AccountView
urlpatterns = [
path('login', views.obtain_auth_token, name="login"),
path('register', AccountView.as_view(), name="register")
]
Of course, you can also implement the user register in views.py.
from django.shortcuts import render
from rest_framework.generics import CreateAPIView
from users.serializers import AccountSerializer
from .models import Account
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework import status
class AccountView(CreateAPIView):
queryset = Account.objects.all()
serializer_class = AccountSerializer
permission_classes = [AllowAny]
def post(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
input_data = serializer.validated_data
username = input_data.get('username')
password = input_data.get('password')
# create user and set password
user = Account.objects.create(username=username)
user.set_password(password)
user.save()
return Response(AccountSerializer(user).data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
wrong username/password. It should works, however I do not recommand doing this for security reasons, you should use the default User Model from django and make a Profile class (which could contain other attributes) for example with a Foreign Key to a User Object.