Reputation: 211
I create custom user model that extends from AbstractBaseUser. I try to connect this model with API using rest framework the register EndPints, getUser and logout is working fine. But when i try to login user it show this message 'Incorrect Credentials'
i try to find the problem and I discover that method authenticate don't work for some resnes
This is My Code
urls.py
from django.urls import path, include
from knox import views as knox_views
# import views
from .views import RegisterAPI, LoginAPI, UserAPI
urlpatterns = [
path('api/auth', include('knox.urls')),
path('api/auth/register', RegisterAPI.as_view()),
path('api/auth/login', LoginAPI.as_view()),
path('api/auth/user', UserAPI.as_view()),
path('api/auth/logout', knox_views.LogoutView.as_view(), name='knox-logout'),
]
custom user model
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
# cerate user manger (replace old user Table with User Table that we cerated)
class UserManager(BaseUserManager):
def create_user(self, phone, password=None, username=None,is_staff=False, is_admain=False, active=True,**extra_fields):
if not phone:
raise ValueError("User must have a phone number")
if not password:
raise ValueError("User must have password")
user = self.model(phone=phone)
user.set_password(password)
user.username = username
user.staff = is_staff
user.admain = is_admain
user.active = active
user.save(using=self.db)
return user
def create_staff(self, phone, password=None, username=None,**extra_fields):
user = self.create_user(phone, password=password,username=username,staff=True)
return user
def create_superuser(self, phone, password=None, username=None,**extra_fields):
user = self.create_user(phone,password=password,username=username)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
# Cerate User Model the will every user will inherit from it
class User(AbstractBaseUser):
phone = models.CharField(max_length=9, unique=True)
username = models.CharField(max_length=60)
active = models.BooleanField(default=True) # Can login
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
date_of_birth = models.DateField(auto_now_add=True)
USERNAME_FIELD = 'phone'
REQUIRED_FIELDS = ['username']
object = UserManager()
def __str__(self):
return self.username
def get_full_name(self):
return self.phone
def get_short_name(self):
return self.username
def is_staff(self):
return self.is_staff
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
@property
def is_superuser(self):
return self.admin
@property
def is_active(self):
return self.active
@property
def is_staff(self):
return self.staff
API.py
from rest_framework import generics, permissions
from rest_framework.response import Response
from knox.models import AuthToken
# import serializers
from .serializers import UserSerializer, RegisterSerializer, LoginSerializer
# Regester API
class RegisterAPI(generics.GenericAPIView):
serializer_class = RegisterSerializer
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]
})
# Login API
class LoginAPI(generics.GenericAPIView):
serializer_class = LoginSerializer
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]
})
# Get User API
class UserAPI(generics.RetrieveAPIView):
permission_classes = [permissions.IsAuthenticated,]
serializer_class = UserSerializer
def get_object(self):
return self.request.user
serializers.py
from rest_framework import serializers
from django.contrib.auth import authenticate
# import user Model
from django.contrib.auth import get_user_model
User = get_user_model()
# User Serializer
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'phone', 'username', 'active', 'staff', 'admin')
# Register Serializer
class RegisterSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'phone', 'username', 'active', 'staff', 'admin', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User.object.create_user(validated_data['phone'], validated_data['username'],validated_data['password'])
return user
# Login Serializer
class LoginSerializer(serializers.Serializer):
phone = serializers.CharField()
password = serializers.CharField()
print("-=-=-=-=-=--=-=-=-=--==-=---")
def validate(self, data):
user = authenticate(**data)
#user = authenticate(phone=data[phone], password=data[password])
# not comming her ....... why ?!!!!
print("next !!")
print("-=-=-=-=-=--=-=-=-=--==-=---")
if user and user.is_active:
return user
raise serializers.ValidationError('Incorrect Credentials')
the API EndPoint return to me this
{
"non_field_errors": [
"Incorrect Credentials"
]
}
Upvotes: 0
Views: 1337
Reputation: 1
I got into the same error and found a way to solve it. Probably for my case but hope for many others too. modify your #settings.py file as follows:
INSTALLED_APPS = [
# ... your other apps
'your_app_name',
]
AUTH_USER_MODEL = 'your_app_name.'your_custom_user_model'
AUTH_USER_MODEL = 'mydatabase.Employee'
Upvotes: 0
Reputation: 4630
In your serializer you are validating phone
and password
field but you are using django-authentication function to validate user. Normally django-authentication takes username
and password
to validate user but your serializer seems not have username
field.
If you want to use authenticate function, first you need to find out the user instance associated with that phone field. One important thing is that as this is an unique field so if user exits surely you want to validate that user.
# Login Serializer
class LoginSerializer(serializers.Serializer):
phone = serializers.CharField()
password = serializers.CharField()
def validate(self, data):
try:
user = User.objects.get(phone=data['phone'])
except User.DoesNotExist:
raise serializers.ValidationError('Incorrect Credentials')
user = authenticate(username=user.username, password=data['password'])
if user and user.is_active:
return user
raise serializers.ValidationError('Incorrect Credentials')
Another important point is that you need to ensure your user is active.
Upvotes: 0