Search code examples
pythondjango-authenticationdjango-generic-views

Django: How to login user directly after registration using generic CreateView


With django generic CreateView I can create a new user account, but how can I login this user automatically after registration using this technique?

urls.py

...    
url( r'^signup/$', SignUpView.as_view(), name = 'user_signup' ),
...

views.py

class SignUpView ( CreateView ) :    
    form_class = AccountCreationForm
    template_name = 'accounts/signup.html'
    success_url = reverse_lazy( 'home' )

forms.py

class AccountCreationForm ( forms.ModelForm ) :        
    def __init__( self, *args, **kwargs ) :
        super( AccountCreationForm, self ).__init__( *args, **kwargs )
        for field in self.fields :
           self.fields[field].widget.attrs['class'] = 'form-control'

    password1 = forms.CharField( label = 'Password', widget = forms.PasswordInput )
    password2 = forms.CharField( label = 'Password confirmation', widget = forms.PasswordInput )

    class Meta :
        model = User
        fields = ( 'email', 'first_name', )

    def clean_password2 ( self ) :
        # Check that the two password entries match
        password1 = self.cleaned_data.get( "password1" )
        password2 = self.cleaned_data.get( "password2" )
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError( "Passwords don't match" )
        return password

    def save( self, commit = True ) :
        # Save the provided password in hashed format
        user = super( AccountCreationForm, self ).save( commit = False )
        user.set_password( self.cleaned_data[ "password1" ] )
        if commit:
            user.save()
        return user

Solution

  • it's maybe late but that was exactly my question, and after some hours of struggling finally find out.

    Maybe you found but if other people are looking for a solution, here is mine.

    You just have to override form_valid() in your class Inheriting CreateView. Here is the example with my own class :

    class CreateArtistView(CreateView):
        template_name = 'register.html'
        form_class = CreateArtistForm
        success_url = '/'
    
        def form_valid(self, form):
            valid = super(CreateArtistView, self).form_valid(form)
            username, password = form.cleaned_data.get('username'), form.cleaned_data.get('password1')
            new_user = authenticate(username=username, password=password)
            login(self.request, new_user)
            return valid
    

    I first catch the value of my parent class method form_valid() in valid, because when you call it, it calls the form.save(), which register your user in database and populate your self.object with the user created.

    After that I had a long problem with my authenticate, returning None. It's because I was calling authenticate() with the django hashed password, and authenticate hash it again.

    Explaining this for you to understand why I use form.cleaned_data.get('username') and not self.object.username.

    I hope it helps you or other, since I didn't find a clear answer on the net.