djangodjango-viewsdjango-authenticationdjango-class-based-viewsdjango-registration

CreateView creates user but doesn't log user in


I am trying to make a class-based registration view equivalent of my old function based registration view. When I register as a new user, a user is created but is not logged in after registration, and this bug only happens when I use class-based registration view. Form doesn't return any errors also.

views.py class-based (doesn't log in after registration)

from django.contrib import messages
from django.contrib.auth import login
from django.urls import reverse_lazy
from django.views.generic import CreateView

from .forms import NewUserForm


class RegisterUserView(CreateView):
    form_class = NewUserForm
    success_url = reverse_lazy('home')
    template_name = 'users/register.html'

    def form_valid(self, form):
        user = form.save()
        login(self.request, user)

        return super().form_valid(form)

    def form_invalid(self, form):
        messages.error(self.request, form.errors)

        return super().form_invalid(form)

views.py function-based (does log in after registration)

from django.contrib import messages
from django.contrib.auth import login
from django.shortcuts import redirect, render

from .forms import NewUserForm


def register_user(request):
    if request.method == "POST":
        form = NewUserForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)

            return redirect('home')

        messages.error(request, form.errors)

    form = NewUserForm(request.POST)

    context = {
        "form": form
    }

    return render(request, "users/register.html", context)

models.py

from django.db import models
from django.contrib.auth.models import AbstractUser


class CustomUser(AbstractUser):
    email = models.EmailField(unique=True)

forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm

from .models import CustomUser


class NewUserForm(UserCreationForm):
    email = forms.EmailField(required=True)

    class Meta:
        model = CustomUser
        fields = ["username", "email", "password1", "password2"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.label_suffix = ""  # Removes ':' as label suffix

        self.fields['username'].help_text = 'Letters, numbers and @/./+/-/_ only.'
        self.fields['password1'].help_text = '8-20 characters, letters and numbers, no spaces.'
        self.fields['password2'].help_text = None

    def save(self, commit=True):
        user = super(NewUserForm, self).save(commit=False)
        user.email = self.cleaned_data['email']
        if commit:
            user.save()
        return user

settings.py

AUTH_USER_MODEL = "users.CustomUser"


Solution

  • I managed to fix this by simply changing CreateView to FormView.

    class RegisterUserView(FormView):
    form_class = NewUserForm
    success_url = reverse_lazy('home')
    template_name = 'users/register.html'
    
    def form_valid(self, form):
        form.save()
        new_user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password1'])
        login(self.request, new_user)
    
        return super().form_valid(form)
    
    def form_invalid(self, form):
        messages.error(self.request, form.errors)
    
        return super().form_invalid(form)
    

    I also added authenticate() to authenticate the user after creating account to prevent any issues with user authentication.