Создать пользователя неактивным по умолчанию (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 ответов

Решение
  1. Избегайте изменения встроенных модулей. Есть лучшие способы сделать вещи.
  2. Как сигналы. Сигналы потрясающие.
  3. В этом случае я бы прикрепил к сигналу pre_save django.contrib.auth.models.Userи вручную исправьте is_active свойство экземпляра модели (если объект новый).
  4. Таким образом, вы можете добавить некоторую логику, чтобы убедиться, что вы правильно помечаете пользователя как неактивного.
  5. Поскольку пользователь, добавленный в 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 установка. Что это делает... это попросить нового потенциального пользователя предоставить дополнительные поля во время процесса регистрации.

Это имеет очень хорошие преимущества:

  1. Вы можете очень элегантно добавить некоторые поля в дополнение к стандартным.
  2. Это работает как для социальной, так и для "обычной" регистрации.
  3. Не требуется исправление сторонних приложений.
  4. Вы все еще можете изменять и поддерживать все в админке.
  5. В пользовательской форме вы получаете доступ к новому пользовательскому экземпляру до того, как он будет сохранен в базе данных. Это означает, что вы можете даже обрабатывать предоставленную информацию, например, создавать для него объект профиля и устанавливать пользователя как неактивного.. все сразу. Это работает, потому что вы можете проверить, все ли в порядке.. и только затем подтвердить выполнение всех этих шагов или отклонить форму с ошибкой проверки.:)

Ну.. звучит хорошо, верно?
Но как именно это работает (то есть как выглядит)?
Я рад, что вы спросили.. ^_^

Для вашего случая использования это может выглядеть примерно так:

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.

Другие вопросы по тегам