简体   繁体   中英

Creating Django users with just an email and password - UserCreationForm

I have the need of create an user account in my application using just the email and password fields. Due to this, my custom user model in my models.py is:

I customize the UserManager to create user

from django.contrib.auth.models import BaseUserManager

class UserManager(BaseUserManager):
    def _create_user(self, email, password, **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, **extra_fields)
            user.set_password(password)
            user.save()
            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_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)

And my User model is:

from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.utils.translation import ugettext_lazy as _

class User(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(unique=True, null=True,
            help_text=_('Required. Letters, digits and ''@/./+/-/_ only.'),
        validators=[RegexValidator(r'^[\w.@+-]+$', _('Enter a valid email address.'), 'invalid')
        ])

    is_staff = models.BooleanField(
        _('staff status'),
        default=False,
        help_text=_('Designates whether the user can log into this site.'),
    )

    is_active = models.BooleanField(
        _('active'),
        default=True,
        help_text=_(
            'Designates whether this user should be treated as active. '
            'Unselect this instead of deleting accounts.'
        ),
    )

    objects = UserManager()
    USERNAME_FIELD = "email"

    class Meta:
        db_table = 'auth_user'
        verbose_name_plural = 'Usuarios en la plataforma'

    def __str__(self):
        return "@{}".format(self.email)

In my settings I've add:

AUTH_USER_MODEL = ‘my_app_name.User’

CREATE USERS - UserCreationForm pre-built class

To create an user, I am using of the UserCreationForm class pre-built in the django core.

In this class the username field is used such as denoted here

According to the above, in my forms.py I have:

from django.contrib.auth.forms import UserChangeForm, UserCreationForm

class CustomUserChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = get_user_model()

class CustomUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = get_user_model()

class UserCreateForm(UserCreationForm):

    class Meta:
        fields = ("email", "password1", "password2",)
        model = get_user_model()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["email"].label = "Email address"

When I try execute the python manage.py makemigrations , I get this traceback output error

    bgarcial@elpug ‹ testing ●● › : ~/workspace/ihost_project
[1] % python manage.py makemigrations accounts 
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line
    utility.execute()
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/core/management/__init__.py", line 341, in execute
    django.setup()
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/__init__.py", line 27, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/apps/registry.py", line 115, in populate
    app_config.ready()
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/contrib/admin/apps.py", line 23, in ready
    self.module.autodiscover()
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/contrib/admin/__init__.py", line 26, in autodiscover
    autodiscover_modules('admin', register_to=site)
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/utils/module_loading.py", line 50, in autodiscover_modules
    import_module('%s.%s' % (app_config.name, module_to_search))
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/home/bgarcial/workspace/ihost_project/accounts/admin.py", line 8, in <module>
    from .forms import CustomUserChangeForm, CustomUserCreationForm
  File "/home/bgarcial/workspace/ihost_project/accounts/forms.py", line 16, in <module>
    class CustomUserCreationForm(UserCreationForm):
  File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/forms/models.py", line 257, in __new__
    raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (username) specified for User
(ihost) 
bgarcial@elpug ‹ testing ●● › : ~/workspace/ihost_project

Of course, I am using UserCreationForm django class core, I am forcing to use the django core functionalities in which the username field is required

How to can I remove the username or modify this?

I know the modify the django core is not recommended, but, how to can I create an user without include the username field making use of UserCreationForm django class core?

I try override the save method of my form in where I create the users, but I don't have clear the process, I think that the core of my inconvenient is in the use of UserCreationForm django class core ..

class UserCreateForm(UserCreationForm):
    class Meta:
        fields = ("email", "password1", "password2",)
        model = get_user_model()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["email"].label = "Email address"

    def save(self, commit=True):
        user = super(UserCreateForm, self).save(commit=False)
        user.email = self.cleaned_data["email"]

        # Tell to Django that not check the username

        if commit:
            user.save()
        return user

If somebody can point me in the right direction will be very much appreciated. :)

I've found a solution that works.

anyways, feel free to suggest better solutions!

Like my inconvenient/error was related with the use of the UserCreationForm class pre-built in the django core which use the username field in their logic , then I proceeded to make the following:

In my forms.py in my class CustomUserCreationForm is a child of the class UserCreationForm , I've override/add to Meta class the attribute fields , using the email field instead of username field. This question post help me with it.

My class CustomUserCreationForm stay as follow:

class CustomUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = get_user_model()
        fields = ('email',)

Then, I proceeded to perform my migrations:

[1] % python manage.py makemigrations accounts 
SystemCheckError: System check identified some issues:

ERRORS:
<class 'accounts.admin.UserAdmin'>: (admin.E033) The value of 'ordering[0]' refers to 'username', which is not an attribute of 'accounts.User'.

This error showed me that the username field is not an attribute of my User model. This means that Django follows trying to ask the username field, even though I overwritten the fields value with the email field.

Of course this is logic because I am still inherit from UserCreationForm class pre-built in the django core

Then, I've add the username field to my User model with null=True attribute, and of this way, the username does not required in the user account creation:

class User(AbstractBaseUser, PermissionsMixin):

    # I had add the username field despite that I don't use in my User model
    username = models.CharField(_('username'), max_length=30, null=True,
            help_text=_('Required. 30 characters or fewer. Letters, digits and ''@/./+/-/_ only.'),
        validators=[RegexValidator(r'^[\w.@+-]+$', _('Enter a valid username.'), 'invalid')
        ])

    email = models.EmailField(unique=True, null=True,
            help_text=_('Required. Letters, digits and ''@/./+/-/_ only.'),
        validators=[RegexValidator(r'^[\w.@+-]+$', _('Enter a valid email address.'), 'invalid')
        ])

  ...

Of this way, I execute my migrations

bgarcial@elpug ‹ testing ●● › : ~/workspace/ihost_project
[1] % python manage.py makemigrations accounts 
Migrations for 'accounts':
  accounts/migrations/0001_initial.py:
    - Create model User
(ihost) 
bgarcial@elpug ‹ testing ●● › : ~/workspace/ihost_project

python manage.py migrate accounts ...

And my username field still persist in my custom user schema, just that is not required and when I created an user from my UserCreateForm class which inherit from UserCreationForm , I can create an user account with just email and password

在此处输入图片说明

I don`t know if this is the best approach to address this inconvenient. Feel free to suggest improvements!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM