Mercurial > public > sg101
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accounts/forms.py Sat May 05 17:10:48 2012 -0500 @@ -0,0 +1,152 @@ +"""forms for the accounts application""" + +import logging + +from django import forms +from django.contrib.auth.models import User +from django.core.urlresolvers import reverse +from django.template.loader import render_to_string +from django.contrib.sites.models import Site +from django.conf import settings + +from core.functions import send_mail +from accounts.models import PendingUser +from accounts.models import IllegalUsername +from accounts.models import IllegalEmail +from antispam.rate_limit import block_ip + + +class RegisterForm(forms.Form): + """Form used to register with the website""" + username = forms.RegexField( + max_length=30, + regex=r'^\w+$', + error_messages={'invalid': ('Your username must be 30 characters or' + ' less and contain only letters, numbers and underscores.')}, + widget=forms.TextInput(attrs={'class': 'text'}), + ) + email = forms.EmailField(widget=forms.TextInput(attrs={'class': 'text'})) + password1 = forms.CharField(label="Password", + widget=forms.PasswordInput(attrs={'class': 'text'})) + password2 = forms.CharField(label="Password confirmation", + widget=forms.PasswordInput(attrs={'class': 'text'})) + agree_age = forms.BooleanField(required=True, + label='I certify that I am over the age of 13', + error_messages={ + 'required': 'Sorry, but you must be over the age of 13 to ' + 'register at our site.', + }) + agree_tos = forms.BooleanField(required=True, + label='I agree to the Terms of Service', + error_messages={ + 'required': 'You have not agreed to our Terms of Service.', + }) + agree_privacy = forms.BooleanField(required=True, + label='I agree to the Privacy Policy', + error_messages={ + 'required': 'You have not agreed to our Privacy Policy.', + }) + question1 = forms.CharField(label="What number appears in the site name?", + widget=forms.TextInput(attrs={'class': 'text'})) + question2 = forms.CharField(label='', required=False, + widget=forms.TextInput(attrs={'style': 'display: none;'})) + + def __init__(self, *args, **kwargs): + self.ip = kwargs.pop('ip', '?') + super(RegisterForm, self).__init__(*args, **kwargs) + + def clean_username(self): + username = self.cleaned_data['username'] + try: + User.objects.get(username=username) + except User.DoesNotExist: + try: + PendingUser.objects.get(username=username) + except PendingUser.DoesNotExist: + try: + IllegalUsername.objects.get(username=username) + except IllegalUsername.DoesNotExist: + return username + self._validation_error("That username is not allowed.", username) + self._validation_error("A pending user with that username already exists.", username) + self._validation_error("A user with that username already exists.", username) + + def clean_email(self): + email = self.cleaned_data['email'] + + if User.objects.filter(email=email).count(): + self._validation_error("A user with that email address already exists.", email) + elif PendingUser.objects.filter(email=email).count(): + self._validation_error("A pending user with that email address already exists.", email) + elif IllegalEmail.objects.filter(email=email).count(): + self._validation_error("That email address is not allowed.", email) + + # email is ok + return email + + def clean_password2(self): + password1 = self.cleaned_data.get("password1", "") + password2 = self.cleaned_data["password2"] + if password1 != password2: + self._validation_error("The two password fields didn't match.") + if len(password1) < 6: + self._validation_error("Please choose a password of 6 characters or more.") + return password2 + + def clean_question1(self): + answer = self.cleaned_data.get('question1') + success = False + if answer: + try: + val = int(answer) + except ValueError: + pass + else: + success = val == 101 + if not success: + self._validation_error("Incorrect answer to our anti-spam question.", answer) + return answer + + def clean_question2(self): + """ + Honeypot field should be empty. + """ + answer = self.cleaned_data.get('question2') + if answer: + block_ip(self.ip) + self._validation_error('Wrong answer #2: %s' % answer) + return answer + + def save(self): + pending_user = PendingUser.objects.create_pending_user(self.cleaned_data['username'], + self.cleaned_data['email'], + self.cleaned_data['password1']) + + # Send the confirmation email + + site = Site.objects.get_current() + admin_email = settings.ADMINS[0][1] + + activation_link = 'http://%s%s' % (site.domain, reverse('accounts.views.register_confirm', + kwargs = {'username' : pending_user.username, 'key' : pending_user.key})) + + msg = render_to_string('accounts/registration_email.txt', + { + 'site_name' : site.name, + 'site_domain' : site.domain, + 'user_email' : pending_user.email, + 'activation_link' : activation_link, + 'username' : pending_user.username, + 'admin_email' : admin_email, + }) + + subject = 'Registration Confirmation for ' + site.name + send_mail(subject, msg, admin_email, [self.cleaned_data['email']]) + logging.info('Accounts/registration conf. email sent to %s for user %s; IP = %s', + self.cleaned_data['email'], pending_user.username, self.ip) + + return pending_user + + def _validation_error(self, msg, param=None): + logging.error('Accounts/registration [%s]: %s (%s)', self.ip, msg, param) + raise forms.ValidationError(msg)