我创建了自AbstractBaseUser扩展的自定义用户模型。我尝试使用rest框架将此模型与API连接 寄存器EndPints,getUser和注销工作正常。但是,当我尝试登录用户时,它会显示此消息“凭据不正确”
我尝试发现问题,但发现该方法对某些Resnes无效
这是我的密码
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'),
]
自定义用户模型
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')
API EndPoint返回给我
{
"non_field_errors": [
"Incorrect Credentials"
]
}
答案 0 :(得分:0)
在序列化器中,您正在验证phone
和password
字段,但是您正在使用django-authentication函数来验证用户。通常,django身份验证需要username
和password
来验证用户,但是您的序列化程序似乎没有username
字段。
如果要使用身份验证功能,首先需要找出与该电话字段关联的用户实例。重要的一点是,由于这是一个唯一字段,因此如果用户确定退出,则需要验证该用户。
# 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')
另一个重要的一点是,您需要确保您的用户处于活动状态。