email login, create and save

87 views
Skip to first unread message

Ali A Cetrefli

unread,
May 4, 2018, 12:51:17 PM5/4/18
to Django developers (Contributions to Django itself)
Dear developers,

Please make new email UserCreateFormbyEmail, UserAuthenticatebyEmail

I know, You have many custom authentication methods, but nature of internet in signup forms is by email not username..

best regards..

Collin Anderson

unread,
May 4, 2018, 1:22:30 PM5/4/18
to django-d...@googlegroups.com
Do you want something like this?

class EmailUserCreationForm(UserCreationForm):
    username = User._meta.get_field('username').formfield(label='Email', validators=[validators.validate_email])

    def save(self, commit=True):
        self.instance.email = self.cleaned_data['username']
        return super().save(commit=commit)


class EmailAuthenticateForm(UserCreationForm):
    username = User._meta.get_field('username').formfield(label='Email')


--
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 django-developers+unsubscribe@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
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/c31d4b3d-c71f-4f0b-b3c4-5be1e8e7d34b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Thanh Tran

unread,
May 6, 2018, 4:35:20 PM5/6/18
to Django developers (Contributions to Django itself)
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'}))

Reply all
Reply to author
Forward
0 new messages