2 Forms and validation code for user registration.
7 from django
import forms
8 from django
.utils
.translation
import ugettext_lazy
as _
9 from django
.contrib
.auth
.models
import User
11 from registration
.models
import RegistrationProfile
14 # I put this on all required fields, because it's easier to pick up
15 # on them with CSS or JavaScript if they have a class of "required"
16 # in the HTML. Your mileage may vary. If/when Django ticket #3515
17 # lands in trunk, this will no longer be necessary.
18 attrs_dict
= { 'class': 'required' }
21 class RegistrationForm(forms
.Form
):
23 Form for registering a new user account.
25 Validates that the requested username is not already in use, and
26 requires the password to be entered twice to catch typos.
28 Subclasses should feel free to add any additional validation they
29 need, but should either preserve the base ``save()`` or implement
30 a ``save()`` which accepts the ``profile_callback`` keyword
31 argument and passes it through to
32 ``RegistrationProfile.objects.create_inactive_user()``.
35 username
= forms
.RegexField(regex
=r
'^\w+$',
37 widget
=forms
.TextInput(attrs
=attrs_dict
),
39 email
= forms
.EmailField(widget
=forms
.TextInput(attrs
=dict(attrs_dict
,
41 label
=_(u
'email address'))
42 password1
= forms
.CharField(widget
=forms
.PasswordInput(attrs
=attrs_dict
, render_value
=False),
44 password2
= forms
.CharField(widget
=forms
.PasswordInput(attrs
=attrs_dict
, render_value
=False),
45 label
=_(u
'password (again)'))
47 def clean_username(self
):
49 Validate that the username is alphanumeric and is not already
54 user
= User
.objects
.get(username__iexact
=self
.cleaned_data
['username'])
55 except User
.DoesNotExist
:
56 return self
.cleaned_data
['username']
57 raise forms
.ValidationError(_(u
'This username is already taken. Please choose another.'))
61 Verifiy that the values entered into the two password fields
62 match. Note that an error here will end up in
63 ``non_field_errors()`` because it doesn't apply to a single
67 if 'password1' in self
.cleaned_data
and 'password2' in self
.cleaned_data
:
68 if self
.cleaned_data
['password1'] != self
.cleaned_data
['password2']:
69 raise forms
.ValidationError(_(u
'You must type the same password each time'))
70 return self
.cleaned_data
72 def save(self
, profile_callback
=None):
74 Create the new ``User`` and ``RegistrationProfile``, and
77 This is essentially a light wrapper around
78 ``RegistrationProfile.objects.create_inactive_user()``,
79 feeding it the form data and a profile callback (see the
80 documentation on ``create_inactive_user()`` for details) if
84 new_user
= RegistrationProfile
.objects
.create_inactive_user(username
=self
.cleaned_data
['username'],
85 password
=self
.cleaned_data
['password1'],
86 email
=self
.cleaned_data
['email'],
87 profile_callback
=profile_callback
)
91 class RegistrationFormTermsOfService(RegistrationForm
):
93 Subclass of ``RegistrationForm`` which adds a required checkbox
94 for agreeing to a site's Terms of Service.
97 tos
= forms
.BooleanField(widget
=forms
.CheckboxInput(attrs
=attrs_dict
),
98 label
=_(u
'I have read and agree to the Terms of Service'))
102 Validate that the user accepted the Terms of Service.
105 if self
.cleaned_data
.get('tos', False):
106 return self
.cleaned_data
['tos']
107 raise forms
.ValidationError(_(u
'You must agree to the terms to register'))
110 class RegistrationFormUniqueEmail(RegistrationForm
):
112 Subclass of ``RegistrationForm`` which enforces uniqueness of
116 def clean_email(self
):
118 Validate that the supplied email address is unique for the
122 if User
.objects
.filter(email__iexact
=self
.cleaned_data
['email']):
123 raise forms
.ValidationError(_(u
'This email address is already in use. Please supply a different email address.'))
124 return self
.cleaned_data
['email']
127 class RegistrationFormNoFreeEmail(RegistrationForm
):
129 Subclass of ``RegistrationForm`` which disallows registration with
130 email addresses from popular free webmail services; moderately
131 useful for preventing automated spam registrations.
133 To change the list of banned domains, subclass this form and
134 override the attribute ``bad_domains``.
137 bad_domains
= ['aim.com', 'aol.com', 'email.com', 'gmail.com',
138 'googlemail.com', 'hotmail.com', 'hushmail.com',
139 'msn.com', 'mail.ru', 'mailinator.com', 'live.com']
141 def clean_email(self
):
143 Check the supplied email address against a list of known free
147 email_domain
= self
.cleaned_data
['email'].split('@')[1]
148 if email_domain
in self
.bad_domains
:
149 raise forms
.ValidationError(_(u
'Registration using free email addresses is prohibited. Please supply a different email address.'))
150 return self
.cleaned_data
['email']