I’m trying to login the users I registered in my registration view (where I get a 200 code that says POST request was successful) but I get “Unable to log in with provided credentials.” when I try to log them in. When I check in the shell with User.objects.all(), I only get my superuser back so I think the users are not being saved to the database. I don’t understand why this is happening so if anyone has an idea, it’d be appreciated.
Here’s the code.
Models:
from django.db import models, transaction from django.conf import settings from django.contrib.auth.models import BaseUserManager, AbstractUser class UserManager(BaseUserManager): @transaction.atomic def create_user(self, email, username, password=False): if not email: raise ValueError('Users must have an email address') if not username: raise ValueError('Users must have an username') user = self.model( email=self.normalize_email(email), username=username, ) user.set_password(password) user.save() return user def get_by_natural_key(self, username): return self.get(username=username) def create_superuser(self, username, password, email): user = self.create_user( username=username, email=email, password=password, ) user.is_superuser = True user.save(using=self._db) return user class User(AbstractUser): email = models.EmailField( verbose_name='email address', max_length=255, unique=True, ) username = models.CharField( verbose_name= 'username', max_length= 50, unique=True, ) is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) objects = UserManager() USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] def __str__(self): return str(self.username)
Serializers:
from django.contrib.auth.models import User from rest_framework import serializers from backend.models import User from django.contrib.sites.shortcuts import get_current_site from django.db.models import Q from rest_framework.validators import UniqueValidator from rest_framework.authtoken.models import Token from django.contrib.auth import authenticate, get_user_model user = get_user_model() class UserRegistrationSerializer(serializers.ModelSerializer): username = serializers.CharField( required=True, validators=[UniqueValidator(queryset=User.objects.all(),lookup='iexact')] ) email = serializers.CharField( required=True, validators=[UniqueValidator(queryset=User.objects.all(),lookup='iexact')] ) password = serializers.CharField( required=True, label="Password", style={'input_type': 'password'} ) password_2 = serializers.CharField( required=True, label="Confirm Password", style={'input_type': 'password'} ) class Meta: model = User fields = ['username', 'email', 'password', 'password_2',] def validate_password(self, value): if len(value) < 8: raise serializers.ValidationError( "Password should be at least 8 characters long.") return value def validate_password_2(self, value): data = self.get_initial() password = data.get('password') if password != value: raise serializers.ValidationError("Passwords don't match.") return value def validate_username(self, value): if User.objects.filter(username=value).exists(): raise serializers.ValidationError("Username already exists.") return value def create(self, validated_data): user = User( email=validated_data['email'], username=validated_data['username'] ) user.set_password(validated_data['password']) user.save() return user class UserLoginSerializer(serializers.ModelSerializer): username = serializers.CharField( required=True, write_only=True, ) token = serializers.CharField( allow_blank=True, read_only=True ) password = serializers.CharField( required=True, write_only=True, style={'input_type': 'password'} ) class Meta(object): model = User fields = ['username', 'password', 'token'] def validate(self, data): username = data.get('username', None) password = data.get('password', None) if username and password: user = authenticate(request=self.context.get('request'), username=username, password=password) if not user: msg = 'Unable to log in with provided credentials.' raise serializers.ValidationError(msg, code='authorization') else: msg = "Must include username and password." raise serializers.ValidationError(msg, code='authorization') data['user'] = user return data
Views:
from django.contrib.auth import get_user_model from django.contrib.sites.shortcuts import get_current_site from rest_framework import generics, permissions, status from rest_framework.authentication import TokenAuthentication from rest_framework.response import Response from backend.models import User from backend.serializers import UserLoginSerializer, UserRegistrationSerializer from backend import serializers from django.contrib.auth.decorators import login_required from rest_framework.authtoken.models import Token User = get_user_model() class UserLoginAPIView(generics.CreateAPIView): permission_classes = (permissions.AllowAny, ) serializer_class = serializers.UserLoginSerializer def post(self, request, *args, **kwargs): serializer = UserLoginSerializer(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] token, created = Token.objects.get_or_create(user=user) return Response({"status": status.HTTP_200_OK, "Token": token.key}) class UserRegistrationAPIView(generics.CreateAPIView): permission_classes = (permissions.AllowAny, ) serializer_class = serializers.UserRegistrationSerializer def post(self, request): serializer = self.serializer_class(data=request.data) if serializer.is_valid(raise_exception=True): return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Advertisement
Answer
The issue was that I needed to add ‘user.set_password(validated_data[‘password’])’ right after the user. That solved it.
def create(self, validated_data): user = User( email=validated_data['email'], username=validated_data['username'] ) user.set_password(validated_data['password']) user.save() return user