comparison accounts/forms.py @ 581:ee87ea74d46b

For Django 1.4, rearranged project structure for new manage.py.
author Brian Neal <bgneal@gmail.com>
date Sat, 05 May 2012 17:10:48 -0500
parents gpp/accounts/forms.py@6a265b5768ca
children 8e6b8ffe5f34
comparison
equal deleted inserted replaced
580:c525f3e0b5d0 581:ee87ea74d46b
1 """forms for the accounts application"""
2
3 import logging
4
5 from django import forms
6 from django.contrib.auth.models import User
7 from django.core.urlresolvers import reverse
8 from django.template.loader import render_to_string
9 from django.contrib.sites.models import Site
10 from django.conf import settings
11
12 from core.functions import send_mail
13 from accounts.models import PendingUser
14 from accounts.models import IllegalUsername
15 from accounts.models import IllegalEmail
16 from antispam.rate_limit import block_ip
17
18
19 class RegisterForm(forms.Form):
20 """Form used to register with the website"""
21 username = forms.RegexField(
22 max_length=30,
23 regex=r'^\w+$',
24 error_messages={'invalid': ('Your username must be 30 characters or'
25 ' less and contain only letters, numbers and underscores.')},
26 widget=forms.TextInput(attrs={'class': 'text'}),
27 )
28 email = forms.EmailField(widget=forms.TextInput(attrs={'class': 'text'}))
29 password1 = forms.CharField(label="Password",
30 widget=forms.PasswordInput(attrs={'class': 'text'}))
31 password2 = forms.CharField(label="Password confirmation",
32 widget=forms.PasswordInput(attrs={'class': 'text'}))
33 agree_age = forms.BooleanField(required=True,
34 label='I certify that I am over the age of 13',
35 error_messages={
36 'required': 'Sorry, but you must be over the age of 13 to '
37 'register at our site.',
38 })
39 agree_tos = forms.BooleanField(required=True,
40 label='I agree to the Terms of Service',
41 error_messages={
42 'required': 'You have not agreed to our Terms of Service.',
43 })
44 agree_privacy = forms.BooleanField(required=True,
45 label='I agree to the Privacy Policy',
46 error_messages={
47 'required': 'You have not agreed to our Privacy Policy.',
48 })
49 question1 = forms.CharField(label="What number appears in the site name?",
50 widget=forms.TextInput(attrs={'class': 'text'}))
51 question2 = forms.CharField(label='', required=False,
52 widget=forms.TextInput(attrs={'style': 'display: none;'}))
53
54 def __init__(self, *args, **kwargs):
55 self.ip = kwargs.pop('ip', '?')
56 super(RegisterForm, self).__init__(*args, **kwargs)
57
58 def clean_username(self):
59 username = self.cleaned_data['username']
60 try:
61 User.objects.get(username=username)
62 except User.DoesNotExist:
63 try:
64 PendingUser.objects.get(username=username)
65 except PendingUser.DoesNotExist:
66 try:
67 IllegalUsername.objects.get(username=username)
68 except IllegalUsername.DoesNotExist:
69 return username
70 self._validation_error("That username is not allowed.", username)
71 self._validation_error("A pending user with that username already exists.", username)
72 self._validation_error("A user with that username already exists.", username)
73
74 def clean_email(self):
75 email = self.cleaned_data['email']
76
77 if User.objects.filter(email=email).count():
78 self._validation_error("A user with that email address already exists.", email)
79 elif PendingUser.objects.filter(email=email).count():
80 self._validation_error("A pending user with that email address already exists.", email)
81 elif IllegalEmail.objects.filter(email=email).count():
82 self._validation_error("That email address is not allowed.", email)
83
84 # email is ok
85 return email
86
87 def clean_password2(self):
88 password1 = self.cleaned_data.get("password1", "")
89 password2 = self.cleaned_data["password2"]
90 if password1 != password2:
91 self._validation_error("The two password fields didn't match.")
92 if len(password1) < 6:
93 self._validation_error("Please choose a password of 6 characters or more.")
94 return password2
95
96 def clean_question1(self):
97 answer = self.cleaned_data.get('question1')
98 success = False
99 if answer:
100 try:
101 val = int(answer)
102 except ValueError:
103 pass
104 else:
105 success = val == 101
106 if not success:
107 self._validation_error("Incorrect answer to our anti-spam question.", answer)
108 return answer
109
110 def clean_question2(self):
111 """
112 Honeypot field should be empty.
113 """
114 answer = self.cleaned_data.get('question2')
115 if answer:
116 block_ip(self.ip)
117 self._validation_error('Wrong answer #2: %s' % answer)
118 return answer
119
120 def save(self):
121 pending_user = PendingUser.objects.create_pending_user(self.cleaned_data['username'],
122 self.cleaned_data['email'],
123 self.cleaned_data['password1'])
124
125 # Send the confirmation email
126
127 site = Site.objects.get_current()
128 admin_email = settings.ADMINS[0][1]
129
130 activation_link = 'http://%s%s' % (site.domain, reverse('accounts.views.register_confirm',
131 kwargs = {'username' : pending_user.username, 'key' : pending_user.key}))
132
133 msg = render_to_string('accounts/registration_email.txt',
134 {
135 'site_name' : site.name,
136 'site_domain' : site.domain,
137 'user_email' : pending_user.email,
138 'activation_link' : activation_link,
139 'username' : pending_user.username,
140 'admin_email' : admin_email,
141 })
142
143 subject = 'Registration Confirmation for ' + site.name
144 send_mail(subject, msg, admin_email, [self.cleaned_data['email']])
145 logging.info('Accounts/registration conf. email sent to %s for user %s; IP = %s',
146 self.cleaned_data['email'], pending_user.username, self.ip)
147
148 return pending_user
149
150 def _validation_error(self, msg, param=None):
151 logging.error('Accounts/registration [%s]: %s (%s)', self.ip, msg, param)
152 raise forms.ValidationError(msg)