django-signup’s documentation¶
django-signup
is a Django app that handles user registration.
Contents:
Installation¶
To install django-signup
, use pip:
pip install django-signup
If you want the latest-and-greatest version, install it with
pip install -e hg+https://bitbucket.org/fcoelho/django-signup#egg=django-signup
Setup¶
You have to add the app to INSTALLED_APPS
and also include some URLs in
your urlconf
:
INSTALLED_APPS = (
...
'signup',
...
)
urlpatterns = patterns('',
...
url(r'^accounts/', include('signup.urls')),
...
)
Settings¶
These are the settings specific to django-signup
.
SIGNUP_ACTIVATION_DAYS
¶
This controls for how many days an instance of
signup.models.Validation
will be valid before being considered
“expired”. It is used on the clear_expired_signups management command.
If not set in the user settings, the default value is 2 days.
SIGNUP_FORM_CLASS
¶
A string with the full dotted name of a class representing the form to be used on the signup page.
If not specified, the signup.forms.DefaultUserCreationForm
class is
used.
SIGNUP_ALLOWED
¶
A boolean indicating whether signup is allowed. If True
, nothing special
happens. If False
, all requests to the account creation page will be
redirected to a template saying that registration is closed.
New in version 0.5.
This can also be a dotted path to a callable that takes no arguments and returns a boolean indicating whether signup is allowed or not.
Signals¶
New in version 0.6.
There are two signals defined in the signup.signals
module:
user_signed_up
and user_activated
. The first is sent right after the
user object has been created. The second is sent after the user has hit his
activation URL and the corresponding Validation
object has been
deleted.
Both signals are sent with two arguments: user
, the user object, and
request
, the view request object.
Templates¶
The app does not ship with any templates. There are some templates in the sample project available in the source distribution, but those are extremely simple and for demonstration purposes only.
These are the templates you should create at the very least:
-
registration/signup_form.html
¶ Holds the registration form. It is displayed by a view which inherits from FormView. It has the following context:
form
: an instance of the configuredSIGNUP_FORM_CLASS
or an instance ofdjango.contrib.auth.forms.UserCreationForm
-
registration/signup_closed.html
¶ A simple page saying that registration is closed. It has no custom context.
-
registration/signup_complete.html
¶ A simple page indicating that the account has been created and an email has been sent to finish the sign up process. It has no special context.
-
registration/activation_failed.html
¶ Should display a message indicating that the activation failed. It has the following context:
activation_key
: The key used to activate the account. It’s part of the URL
-
registration/activation_complete.html
¶ Should display a message saying that the account was successfully activated. It has no special context.
-
registration/activation_email.txt
¶ Contains the email subject and body, in text and optional html format. This template has a special “syntax” in order to include the subject and body in the same file. A sample file is shown below. Empty lines at the begin and end of each block are stripped away.
-- title=subject This is the subject of the email, multiple lines will be joined -- title=txt This is the text part of the email -- title=html This is the html part of the email, it's optional
This template has the following context:
url
: The full url to be used to activate the account. Includes the domain and pathactivation_days
: How many days the user has to activate his account
Management commands¶
Until now, there is only one management command, documented below.
clear_expired_signups
¶
This command is used to delete from the database user registrations that are more than SIGNUP_ACTIVATION_DAYS days old and haven’t been activated yet.
It deletes both the signup.models.Validation
instance and the user
model instance. By that time, it’s worth noting that the username [1]
registered by the original user becomes available again. If the original user
still wants to keep that username, it has to register again.
Footnotes
[1] | “username”, here, refers to the field marked as USERNAME_FIELD in current installed user model. |
Admin interface¶
django-signup
adds its signup.models.Validation
class to the admin
interface for easy inspection of the current validations.
In addition, you can also resend the activation emails if necessary. To do
that, select the target validation instances and, from the drop down menu,
select Resend activation email
.
Using custom user models¶
This app was created to be used with custom user models, which were introduced
in Django 1.5. While the basic configuration in Setup allows you to use
django-signup
with the default user model, some extra configuration is
needed in order to work with custom user models.
The custom user model¶
Consider the following user model and associated manager:
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('missing email')
user = self.model(email=email)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
#for this example, nothing special happens here
return self.create_user(email, password)
class CustomUser(AbstractBaseUser):
email = models.EmailField(
max_length=254,
unique=True,
db_index=True
)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
def get_short_name(self):
return self.email
def get_full_name(self):
return self.email
This model has, in practice, two fields: email
and password
, the
latter which is provided by AbstractBaseUser
.
The custom sign up form¶
Requirements¶
When this user model is installed (see the docs),
it is already available to Django, but django-signup
requires you to
create a custom version of what Django provides as
UserCreationForm.
This form should have all the necessary information needed to create a custom
user model instance through the CustomUser.objects.create_user
method.
What that really means is:
For every field in
CustomUser.REQUIRED_FIELDS
plusCustomUser.USERNAME_FIELD
, there should be a field of the same name in the sign up form;The only exception is the
password
field, which is populated from three possible different sources:password
,password1
, orpassword2
. This is to accommodate forms which have duplicated fields for password checking (which you should do anyway).When calling
create_user
,django-signup
will use the first available value from those three options, so make sure that, if you have more than one password field, the values match. Ensure that with aclean_*
method on the form, as shown below.The drawback of this approach is that you have to call your password fields
password{,1,2}
instead of, say,pw
or anything else.
Implementation¶
For the user model described above, this form might look like the following:
from django import forms
from your_app.models import CustomUser
class UserSignUpForm(forms.Form):
email = forms.EmailField()
password1 = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(widget=forms.PasswordInput)
def clean_email(self):
email = self.cleaned_data['email'].strip()
try:
CustomUser.objects.get(email__iexact=email)
raise forms.ValidationError('email already exists')
except CustomUser.DoesNotExist:
return email
def clean_password2(self):
pw1 = self.cleaned_data.get('password1')
pw2 = self.cleaned_data.get('password2')
if pw1 and pw2 and pw1 == pw2:
return pw2
raise forms.ValidationError("passwords don't match")
Note that you should implement whatever logic you need to verify your data here. In this case, we’re checking for uniqueness of the email field and that both passwords match. The email field is also going to be checked when the new user is about to be inserted at the database, but by performing our check in the form we’re able to provide the user with a meaningful message about why the signup process didn’t go as expected.
Using the new form¶
Next, you have to tell django-signup
that you want to use this specific
form during the registration process. Suppose that the above form is inside
the your_app/forms.py
file. Then, you have to add the following to your
project settings:
SIGNUP_FORM_CLASS = 'your_app.forms.UserSignUpForm'