over 1 year ago

There are some pitfalls when you need to create and login users manually in Django. Let's create a user first:

def view_handler(request):
    username = request.POST.get('username', None)
    password = request.POST.get('username', None)

Note that request.POST.get('username', None) should be used instead of request.POST['username']. If the later is used, you will get this error:

MultiValueDictKeyError

Once the username and password are extracted, let's create the user

User.objects.create(username=username, password=password, email=email) # DON'T DO THIS

The above code is wrong. Because when create is used instead of create_user, the user's password is not hashed. You will see the user's password is stored in clear text in the database, which is not the right thing to do.

So you should use the following instead:

User.objects.create_user(username=username, password=password, email=None)

What if you want to test if the user you are about to create has already existed:

user, created = User.objects.get_or_create(username=username, email=None)
if created:
    user.set_password(password) # This line will hash the password

    user.save() #DO NOT FORGET THIS LINE

get_or_create will get the existing user or create a new one. Two values are returned, an user object and a boolean flag created indicating whether if the user created is a new one (i.e. created = True) or an existing one (i.e. created = False)

It is import to not forget including user.save() in the end. Because set_password does NOT save the password to the database.

Login

Now a user has been created successfully, the next step is to login.

user = authenticate(username=email, password=password)
login(request, user)

authenticate() only sets user.backend to whatever authentication backend Django uses. So the code above is equivlent to:

user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)

Django's documentation recommends the first way of doing it. However, there is an use case for the second approach. When you want to login an user without a password:

username = self.request.GET.get('username')
user = User.objects.get(username=username)
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)

The is used when security isn't an issue but you still want to distinguish between who's who on your site.

So to sum up the code above, here is the view_handler that manually create and login an user:

def view_handler(request, *args, **kwargs):
    email = request.POST.get('email', None)
    password = request.POST.get('password', None)
    if email and password:
        user, created = User.objects.get_or_create(username=email,
                                                   email=email)
        if created:
            user.set_password(password)
            user.save()

        user = authenticate(username=email, password=password)
        login(request, user)
        return HttpResponseRedirect('where_ever_should_be_redirect_to')
    else:
        # return error or redirect to login page again
← Javascript's Bitwise Not operator (tilde) Django how to reverse urls belonged to other apps →
 
comments powered by Disqus