Dear Ali,
First, Collin's code works if you just want a workaround to the default
authentication class. However, if you mean having User Authentication with
email as the primary attribute, then you have to override the default
authentication/user object. Django currently allows custom user models,
forms, etc. The following code works for me if you want to work with email
through out the project instead of the default username:
#models.py
#here, I basically create a user class that can be authenticated using
email and password through a user manager and a user model object
class MyUserManager(BaseUserManager):
"""
A custom user manager to deal with emails as unique identifiers for auth
instead of usernames. The default that's used is "UserManager"
"""
def _create_user(self, email, password, first_name=None,
last_name=None, is_active=True, is_staff=False, is_admin=False,
**extra_fields):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
email = self.normalize_email(email)
user = self.model(email=email, firstName=first_name,
lastName=last_name)
user.set_password(password)
user.staff = is_staff
user.admin = is_admin
user.is_superuser = extra_fields.get('is_superuser', False)
user.is_active = is_active
user.save()
return user
def create_user(self, email, password = None, first_name=None,
last_name=None, is_active=True, is_staff=False, is_admin=False,
**extra_fields):
user_obj =self.model.objects.filter(email=email)
if(user_obj.exists() and not None):
return user_obj[0]
return self._create_user(email, password = password,
first_name=first_name, last_name=last_name, is_active=is_active,
is_staff=is_staff, is_admin=is_admin, **extra_fields)
def create_staffuser(self, email, first_name=None, last_name=None,
password=None):
user = self.create_user(
email,
password=password,
first_name = first_name,
last_name = last_name,
is_staff=True
)
return user
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_admin', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(verbose_name='email address',
max_length=255, unique = True, null = True)
is_active = models.BooleanField(verbose_name='active', default=True)
staff = models.BooleanField(verbose_name= 'staff status', default =
False)
admin = models.BooleanField(verbose_name= 'admin status', default =
False)
firstName = models.CharField(max_length=32, default='', null=True,
blank=True)
lastName = models.CharField(max_length=32, default='', null=True,
blank=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone
number must be entered in the format: '+999999999'. Up to 15 digits
allowed.")
phone = models.CharField(validators=[phone_regex],max_length =
15, null=True, blank = True)
USERNAME_FIELD = 'email'
objects = MyUserManager()
def __str__(self):
return self.email
#settings.py make sure to include AUTH_USER_MODEL= '<path to your user
model>'
#forms.py
#note that the form styling is embedded into the form as widgets (you might
want something different).
class UserCreateFormbyEmail(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username
and
password.
"""
error_messages = {
'password_mismatch': _("The two password fields didn't match."),
}
password1 = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput,
help_text=password_validation.password_validators_help_text_html(),
)
password2 = forms.CharField(
label=_("Password confirmation"),
widget=forms.PasswordInput,
help_text=_("Enter the same password as before, for verification."),
)
class Meta:
model = get_user_model()
fields = ("email", "firstName", "lastName")
field_classes = {'email': UsernameField,}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self._meta.model.USERNAME_FIELD in self.fields:
self.fields[self._meta.model.USERNAME_FIELD].widget.attrs.update({'autofocus':
True})
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def clean_email(self):
email = self.cleaned_data.get('email')
if(email and get_user_model().objects.filter(email=email).exists()):
raise forms.ValidationError('This email address has been
registered')
return email
def _post_clean(self):
super()._post_clean()
# Validate the password after self.instance is updated with form
data
# by super().
password = self.cleaned_data.get('password2')
if password:
try:
password_validation.validate_password(password,
self.instance)
except forms.ValidationError as error:
self.add_error('password2', error)
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAuthenticatebyEmail(AuthenticationForm):
""" because we override the default user class, the username field is
now email, not strings"""
username = UsernameField(required=True,label="Username",
widget=forms.TextInput(attrs={
'class': 'form-control login-field',
'name': 'email',
'placeholder': 'Email'}))
password = ReadOnlyPasswordHashField(required=True,label="Password",
widget=forms.PasswordInput(attrs={
'class': 'form-control login-field',
'name': 'password',
'placeholder':'Username'}))
--
You received this message because you are subscribed to the Google Groups
"Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/0ae3c698-ffbf-4bd6-b27a-2f43f3d13d58%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.