Created
January 8, 2011 18:50
-
-
Save fohlin/771052 to your computer and use it in GitHub Desktop.
A version of Django's UserCreationForm that uses email instead of username, with some nifty features. (Maybe not super robust yet, in terms of concurrency...)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from django import forms | |
from django.contrib.auth.models import User | |
from django.contrib.auth.forms import UserCreationForm | |
class UniqueUserEmailField(forms.EmailField): | |
""" | |
An EmailField which only is valid if no User has that email. | |
""" | |
def validate(self, value): | |
super(forms.EmailField, self).validate(value) | |
try: | |
User.objects.get(email = value) | |
raise forms.ValidationError("Email already exists") | |
except User.MultipleObjectsReturned: | |
raise forms.ValidationError("Email already exists") | |
except User.DoesNotExist: | |
pass | |
class ExtendedUserCreationForm(UserCreationForm): | |
""" | |
Extends the built in UserCreationForm in several ways: | |
* Adds an email field, which uses the custom UniqueUserEmailField, | |
that is, the form does not validate if the email address already exists | |
in the User table. | |
* The username field is generated based on the email, and isn't visible. | |
* first_name and last_name fields are added. | |
* Data not saved by the default behavior of UserCreationForm is saved. | |
""" | |
username = forms.CharField(required = False, max_length = 30) | |
email = UniqueUserEmailField(required = True, label = 'Email address') | |
first_name = forms.CharField(required = True, max_length = 30) | |
last_name = forms.CharField(required = True, max_length = 30) | |
def __init__(self, *args, **kwargs): | |
""" | |
Changes the order of fields, and removes the username field. | |
""" | |
super(UserCreationForm, self).__init__(*args, **kwargs) | |
self.fields.keyOrder = ['email', 'first_name', 'last_name', | |
'password1', 'password2'] | |
def __generate_username(self, email): | |
""" | |
A simple way of deriving a username from an email address. | |
Hat tip: http://bit.ly/eIUR5R | |
>>> User.objects.all().order_by('-id')[0].id | |
1 | |
>>> self.__generate_username("[email protected]") | |
abcabc2 | |
>>> self.__generate_username("[email protected]") | |
heysup3 | |
""" | |
# TODO: Something more efficient? | |
highest_user_id = User.objects.all().order_by('-id')[0].id | |
leading_part_of_email = email.split('@',1)[0] | |
leading_part_of_email = re.sub(r'[^a-zA-Z0-9+]', '', | |
leading_part_of_email) | |
truncated_part_of_email = leading_part_of_email[:3] \ | |
+ leading_part_of_email[-3:] | |
derived_username = truncated_part_of_email + str(highest_user_id+1) | |
return derived_username | |
def clean(self, *args, **kwargs): | |
""" | |
Normal cleanup + username generation. | |
""" | |
cleaned_data = super(UserCreationForm, self).clean(*args, **kwargs) | |
if cleaned_data.has_key('email'): | |
cleaned_data['username'] = self.__generate_username( | |
cleaned_data['email']) | |
return cleaned_data | |
def save(self, commit=True): | |
""" | |
Saves the email, first_name and last_name properties, after the normal | |
save behavior is complete. | |
""" | |
user = super(UserCreationForm, self).save(commit) | |
if user: | |
user.email = self.cleaned_data['email'] | |
user.first_name = self.cleaned_data['first_name'] | |
user.last_name = self.cleaned_data['last_name'] | |
user.set_password(self.cleaned_data['password1']) | |
if commit: | |
user.save() | |
return user | |
great, worked lot for me
instead of:
User.objects.get(email = value)
you could just call if User.objects.filter(email=value).exists():
and then just raise ValidationError
if email exists.
that way you don't have to use try catch
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This helped me tremendously. Thank you.
Here is what I used to generate a username from an email address. I like it better because it actually checks the database first making it more deterministic. The method also attempts to use as much of the users current email username as possible. Random digits are only appended incrementally as a last resort.