Создать пользователя неактивным по умолчанию (is_active default False)
У меня есть аутентификация на Facebook на моем сайте, которую я использую https://github.com/omab/django-social-auth
Я хочу перенаправить пользователей на другой сайт, чтобы они заполнили свои данные. Поэтому я хочу, чтобы пользователи были неактивными, когда они сначала проходят проверку подлинности с помощью своих учетных записей Facebook, а затем, после того как они заполнили форму, я сохраню их как активных пользователей.
Я манипулировал django/contrib/auth/models.py в моей среде как с полями is_active по умолчанию =False; но они сохраняются как активный пользователь, но результат тот же, даже если я добавляю обычного пользователя из панели администратора. Есть что-то, чего мне не хватает?
class User(models.Model):
"""
Users within the Django authentication system are represented by this
model.
Username and password are required. Other fields are optional.
"""
username = models.CharField(_('username'), max_length=30, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, numbers and '
'@/./+/-/_ characters'))
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('e-mail address'), blank=True)
password = models.CharField(_('password'), max_length=128)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(_('active'), default=False,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
is_superuser = models.BooleanField(_('superuser status'), default=False,
help_text=_('Designates that this user has all permissions without '
'explicitly assigning them.'))
last_login = models.DateTimeField(_('last login'), default=timezone.now)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
groups = models.ManyToManyField(Group, verbose_name=_('groups'),
blank=True, help_text=_('The groups this user belongs to. A user will '
'get all permissions granted to each of '
'his/her group.'))
user_permissions = models.ManyToManyField(Permission,
verbose_name=_('user permissions'), blank=True,
help_text='Specific permissions for this user.')
objects = UserManager()
def create_user(self, username, email=None, password=None):
"""
Creates and saves a User with the given username, email and password.
"""
now = timezone.now()
if not username:
raise ValueError('The given username must be set')
email = UserManager.normalize_email(email)
user = self.model(username=username, email=email,
is_staff=False, is_active=False, is_superuser=False,
last_login=now, date_joined=now)
user.set_password(password)
user.save(using=self._db)
return user
5 ответов
- Избегайте изменения встроенных модулей. Есть лучшие способы сделать вещи.
- Как сигналы. Сигналы потрясающие.
- В этом случае я бы прикрепил к сигналу pre_save
django.contrib.auth.models.User
и вручную исправьтеis_active
свойство экземпляра модели (если объект новый). - Таким образом, вы можете добавить некоторую логику, чтобы убедиться, что вы правильно помечаете пользователя как неактивного.
- Поскольку пользователь, добавленный в Admin, вероятно, должен быть активным, если администратор помечает их как активные.
jack_shed предложил сигналы, которые помогли мне найти направление для его принятия. Но была еще работа, чтобы выяснить, как именно тестировать и модифицировать после получения сигнала.
Вот что сработало для меня.
from django.dispatch import receiver
from django.db.models.signals import pre_save
from django.contrib.auth.models import User
@receiver(pre_save, sender=User)
def set_new_user_inactive(sender, instance, **kwargs):
if instance._state.adding is True:
print("Creating Inactive User")
instance.is_active = False
else:
print("Updating User Record")
Это отловит действие создания пользователя до сохранения, а затем проверит, является ли это состояние экземпляра "добавлением" или нет. Это различает создание и обновление экземпляра модели.
Если вы не выполните этот тест, то при обновлении пользователя для is_active также устанавливается значение False, и в конечном итоге нет возможности активировать их через django.
Элегантное решение при использовании Джанго-Аллаута.
Есть еще одно очень хорошее решение, которое очень похоже на то, что вы хотите.
Я создал пользовательскую форму (в моем случае ModelForm), которую я могу передать django-allauth через ACCOUNT_SIGNUP_FORM_CLASS
установка. Что это делает... это попросить нового потенциального пользователя предоставить дополнительные поля во время процесса регистрации.
Это имеет очень хорошие преимущества:
- Вы можете очень элегантно добавить некоторые поля в дополнение к стандартным.
- Это работает как для социальной, так и для "обычной" регистрации.
- Не требуется исправление сторонних приложений.
- Вы все еще можете изменять и поддерживать все в админке.
- В пользовательской форме вы получаете доступ к новому пользовательскому экземпляру до того, как он будет сохранен в базе данных. Это означает, что вы можете даже обрабатывать предоставленную информацию, например, создавать для него объект профиля и устанавливать пользователя как неактивного.. все сразу. Это работает, потому что вы можете проверить, все ли в порядке.. и только затем подтвердить выполнение всех этих шагов или отклонить форму с ошибкой проверки.:)
Ну.. звучит хорошо, верно?
Но как именно это работает (то есть как выглядит)?
Я рад, что вы спросили.. ^_^
Для вашего случая использования это может выглядеть примерно так:
settings.py
[...]
ACCOUNT_SIGNUP_FORM_CLASS = "<your_app>.forms.SignupForm"
[...]
forms.py
class SignupForm(forms.Form):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.is_active = False
user.save()
Я думаю, что лучшим подходом было бы настроить собственный менеджер моделей, оставив пользовательское значение неактивным по умолчанию.
Создайте в своем приложении: project_app/managers.py:
# project_app/managers.py
from django.contrib.auth.base_user import BaseUserManager
class UserManager(BaseUserManager):
def create_user(self, username, email=None, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
extra_fields.setdefault('is_active', False)
return self._create_user(username, email, password, **extra_fields)
и в ваших моделях:
#project_app/models.py
from .managers import UserManager
from django.contrib.auth.models import AbstractUser
class UserManager(AbstractUser):
objects = UserManager()
# your custom fields go here.
В общем, для проверки электронной почты в Django есть своя таблица. Вы можете проверить, например, mysql> Выберите * From account_emailconfirmation; Так не могли бы вы просто проверить, есть ли адрес электронной почты в этой таблице?
Кстати, если электронные письма не отправляются на ваш почтовый ящик: я много боролся и обнаружил, что эта конфигурация отсутствует: DEFAULT_FROM_EMAIL = ' [email protected] '. В противном случае это webmaster@... который у меня не работал с mod_wsgi.