The basic idea is that an anonymous user can create a new account, but cannot login until they activate their account by clicking a link they'll receive in an activation email. It's a way to automatically verify that the new user has a valid email address, which is generally an acceptable proxy for proving that they're human. Here's an Information Architecture diagram, again using jjg's visual vocabulary.
Here's a more in-depth walk-thru with our fictional user named Bob:
- Bob encounters a section of the site that requires an account, and is redirected to the login page.
- But Bob does not have an account, so he goes to the registration page where he fills out a registration form.
- After submitting the registration form, Bob is taken to a page telling him that he needs to activate his account by clicking a link in an email that he should be receiving shortly.
- Bob checks his email, finds the activation email, and clicks the activation link.
- Bob is taken to a page that tells him his account is active, and he can now login.
As with password reset, I think the last step is unnecessary, and Bob should be automatically logged in when his account is activated. But to do that, you'll have to write your own custom
activate view. Luckily, this isn't very hard. If you take a look at the code for registration.views.activate, the core code is actually quite simple:
from registration.models import RegistrationProfile def activate(request, activation_key): user = RegistrationProfile.objects.activate_user(activation_key.lower()) if not user: # handle invalid activation key else: # do stuff with the user, such as automatically login, then redirect
The rest of the custom
activate view is up to you.
Django comes with a lot of great built-in functionality. One of the most useful contrib apps is authentication, which (among other things) provides views for login, logout, and password reset. Login & logout are self-explanatory, but resetting a password is, by nature, somewhat complicated. Because it's a really bad idea to store passwords as plaintext, you can't just send a user their password when they forget it. Instead, you have to provide a secure mechanism for users to change their password themselves, even if they can't remember their original password. Lucky for us, Django auth provides this functionality out of the box. All you need to do is create the templates and hook-up the views. The code you need to write to make this happen is pretty simple, but it can be a bit tricky to understand how it all works together. There's actually 4 separate view functions that together provide a complete password reset mechanism. These view functions are
Here's an Information Architecture diagram showing how these views fit together, using Jesse James Garrett's Visual Vocabulary. The 2 black dots are starting points, and the circled black dot is an end point.
Here's a more in-depth walk-thru of what's going on, with a fictional user named Bob:
- Bob tries to login and fails, probably a couple times. Bob clicks a "Forgot your password?" link, which takes him to the
- Bob enters his email address, which is then used to find his User account.
- If Bob's User account is found, a password reset email is sent, and Bob is redirected to the
password_reset_doneview, which should tell him to check his email.
- Bob leaves the site to check his email. He finds the password reset email, and clicks the password reset link.
- Bob is taken to the
password_reset_confirmview, which first validates that he can reset his password (this is handled with a hashed link token). If the token is valid, Bob is allowed to enter a new password. Once a new password is submitted, Bob is redirected to the
- Bob can now login to your site with his new password.
This final step is the one minor issue I have with Django's auth password reset. The user just changed their password, why do they have to enter it again to login? Why can't we eliminate step 6 altogether, and automatically log the user in after they reset their password? In fact, you can eliminate step 6 with a bit of hacking on your own authentication backend, but that's a topic for another post.