1 from datetime import date
3 from django import forms
4 from django.conf import settings
5 from django.contrib.auth import authenticate
6 from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
7 from django.contrib.auth.models import User
8 from django.core.exceptions import ValidationError
9 from django.utils.translation import ugettext_lazy as _
11 from philo.contrib.waldo.tokens import REGISTRATION_TIMEOUT_DAYS
14 class EmailInput(forms.TextInput):
15 """Displays an HTML5 email input on browsers which support it and a normal text input on other browsers."""
19 class RegistrationForm(UserCreationForm):
21 Handles user registration. If :mod:`recaptcha_django` is installed on the system and :class:`recaptcha_django.middleware.ReCaptchaMiddleware` is in :setting:`settings.MIDDLEWARE_CLASSES`, then a recaptcha field will automatically be added to the registration form.
23 .. seealso:: `recaptcha-django <http://code.google.com/p/recaptcha-django/>`_
26 #: An :class:`EmailField` using the :class:`EmailInput` widget.
27 email = forms.EmailField(widget=EmailInput)
29 from recaptcha_django import ReCaptchaField
33 if 'recaptcha_django.middleware.ReCaptchaMiddleware' in settings.MIDDLEWARE_CLASSES:
34 recaptcha = ReCaptchaField()
36 def clean_username(self):
37 username = self.cleaned_data['username']
39 # Trivial case: if the username doesn't exist, go for it!
41 user = User.objects.get(username=username)
42 except User.DoesNotExist:
45 if not user.is_active and (date.today() - user.date_joined.date()).days > REGISTRATION_TIMEOUT_DAYS and user.last_login == user.date_joined:
46 # Then this is a user who has not confirmed their registration and whose time is up. Delete the old user and return the username.
50 raise ValidationError(_("A user with that username already exists."))
52 def clean_email(self):
53 if User.objects.filter(email__iexact=self.cleaned_data['email']):
54 raise ValidationError(_('This email is already in use. Please supply a different email address'))
55 return self.cleaned_data['email']
58 username = self.cleaned_data['username']
59 email = self.cleaned_data['email']
60 password = self.cleaned_data['password1']
61 new_user = User.objects.create_user(username, email, password)
62 new_user.is_active = False
67 class UserAccountForm(forms.ModelForm):
68 """Handles a user's account - by default, :attr:`auth.User.first_name`, :attr:`auth.User.last_name`, :attr:`auth.User.email`."""
69 first_name = User._meta.get_field('first_name').formfield(required=True)
70 last_name = User._meta.get_field('last_name').formfield(required=True)
71 email = User._meta.get_field('email').formfield(required=True, widget=EmailInput)
73 def __init__(self, user, *args, **kwargs):
74 kwargs['instance'] = user
75 super(UserAccountForm, self).__init__(*args, **kwargs)
77 def email_changed(self):
78 """Returns ``True`` if the email field changed value and ``False`` if it did not, or if there is no email field on the form. This method must be supplied by account forms used with :mod:`~philo.contrib.waldo`."""
79 return 'email' in self.changed_data
81 def reset_email(self):
83 ModelForms modify their instances in-place during :meth:`_post_clean`; this method resets the email value to its initial state and returns the altered value. This is a method on the form to allow unusual behavior such as storing email on a :class:`UserProfile`.
86 email = self.instance.email
87 self.instance.email = self.initial['email']
88 self.cleaned_data.pop('email')
92 def set_email(cls, user, email):
94 Given a valid instance and an email address, correctly set the email address for that instance and save the changes. This is a class method in order to allow unusual behavior such as storing email on a :class:`UserProfile`.
103 fields = ('first_name', 'last_name', 'email')
106 class WaldoAuthenticationForm(AuthenticationForm):
107 """Handles user authentication. Checks that the user has not mistakenly entered their email address (like :class:`django.contrib.admin.forms.AdminAuthenticationForm`) but does not require that the user be staff."""
108 ERROR_MESSAGE = _("Please enter a correct username and password. Note that both fields are case-sensitive.")
111 username = self.cleaned_data.get('username')
112 password = self.cleaned_data.get('password')
113 message = self.ERROR_MESSAGE
115 if username and password:
116 self.user_cache = authenticate(username=username, password=password)
117 if self.user_cache is None:
119 # Maybe they entered their email? Look it up, but still raise a ValidationError.
121 user = User.objects.get(email=username)
122 except (User.DoesNotExist, User.MultipleObjectsReturned):
125 if user.check_password(password):
126 message = _("Your e-mail address is not your username. Try '%s' instead.") % user.username
127 raise ValidationError(message)
128 elif not self.user_cache.is_active:
129 raise ValidationError(message)
130 self.check_for_test_cookie()
131 return self.cleaned_data