Создание пользователей Django с помощью только электронной почты и пароля - UserCreationForm

69
6

Мне нужно создать учетную запись пользователя в моем приложении, используя только поля email и password. Из-за этого моя пользовательская модель в моих models.py:

Я настраиваю UserManager для создания пользователя

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)

И моя модель пользователя:

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)

В моих настройках я добавляю:

AUTH_USER_MODEL = ‘my_app_name.User

СОЗДАТЬ ПОЛЬЗОВАТЕЛЕЙ - предварительно созданный класс UserCreationForm

Чтобы создать пользователя, я использую класс UserCreationForm предварительно встроенный в ядро django.

В этом классе используется поле имени пользователя, например, здесь

Согласно вышеизложенному, в моих forms.py у меня есть:

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"

Когда я пытаюсь выполнить python manage.py makemigrations, я получаю эту ошибку вывода трассировки

    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

Конечно, я использую UserCreationForm класса UserCreationForm django, я заставляю использовать функциональные возможности ядра django, в которых требуется поле имени пользователя

Как удалить имя пользователя или изменить его?

Я знаю, что изменение ядра django не рекомендуется, но как я могу создать пользователя без включения поля имени пользователя, использующего UserCreationForm класса UserCreationForm django?

Я пытаюсь переопределить метод сохранения моей формы в том месте, где я создаю пользователей, но у меня нет четкого процесса, я думаю, что ядро моего неудобства связано с использованием класса 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

Если кто-то может указать мне в правильном направлении, будет очень благодарен. :)

спросил(а) 2017-07-13T16:22:00+03:00 3 года, 2 месяца назад
1
Решение
56

Я нашел решение, которое работает.

в любом случае, не стесняйтесь предлагать лучшие решения!

Как и моя неудобная/ошибка связана с использованием класса UserCreationForm предварительно встроенного в ядро django, которое использует поле имени пользователя в своей логике, затем я сделал следующее:

В моем form.py в моем классе CustomUserCreationForm является дочерним элементом класса UserCreationForm, я переопределяю/добавляю в Meta класс fields атрибутов, используя поле email вместо поля имени username. Этот вопрос помог мне с этим.

Мой класс CustomUserCreationForm остается следующим:

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

Затем я начал выполнять мои миграции:

[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'.

Эта ошибка показала мне, что поле username не является атрибутом моей модели User. Это означает, что Django следует за попыткой задать поле имени пользователя, даже если я перезаписал значение fields в поле email.

Конечно, это логично, потому что я все еще наследую класс UserCreationForm предварительно встроенный в ядро django

Затем я добавлю поле username в мою модель пользователя с атрибутом null = True, и таким образом, имя пользователя не требуется в создании учетной записи пользователя:

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')
])

...

Таким образом, я выполняю свои миграции

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 ...

И мое поле имени пользователя по-прежнему сохраняется в моей пользовательской схеме, просто это не требуется, и когда я создал пользователя из моего класса UserCreateForm который наследуется от UserCreationForm, я могу создать учетную запись пользователя только с электронной почтой и паролем

enter image description here

Я не знаю, является ли это наилучшим подходом к решению этой неудобной ситуации. Не стесняйтесь предлагать улучшения!

ответил(а) 2017-07-13T21:09:00+03:00 3 года, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема