【问题标题】:Create user inactive as default (is_active default False)默认创建用户不活动(is_active 默认为 False)
【发布时间】:2013-02-13 21:32:52
【问题描述】:

我在我使用omab / django-social-auth的网站中有facebook身份验证

我想将用户重定向到另一个网站,让他们填写详细信息。所以我想让用户在他们第一次使用他们的 Facebook 帐户进行身份验证时处于非活动状态,然后在他们完成表单后我将它们保存为活动用户。

我在我的环境下操作了 django/contrib/auth/models.py,就像使用 is_active 字段一样 default=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

【问题讨论】:

    标签: django django-models django-authentication


    【解决方案1】:

    使用 django-allauth 时的优雅解决方案。

    还有另一种非常好的解决方案..听起来很像您想要的。

    我创建了一个自定义表单(在我的例子中是 ModelForm),我可以通过 ACCOUNT_SIGNUP_FORM_CLASS 设置将其交给 django-allauth。这是做什么的......是要求新的潜在用户在注册过程中提供额外的字段。

    这有一些非常好的优点:

    1. 除了默认内容之外,您还可以非常优雅地添加一些字段。
    2. 它适用于社交和“正常”注册。
    3. 无需修补第三方应用程序。
    4. 您仍然可以在管理员中修改和维护所有内容。
    5. 在自定义表单中,您可以在新用户实例保存到 数据库。这意味着您甚至可以一次性处理提供的信息,例如为他创建一个配置文件对象并将用户设置为非活动..all。 这是有效的,因为您可以检查一切是否正常......然后才承诺执行所有这些步骤或拒绝带有验证错误的表单。 :)

    嗯..听起来不错吧?
    但它究竟是如何工作的(即看起来像)?
    我很高兴你问.. ^_^

    对于您的用例,它可能看起来像这样:

    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()
    

    【讨论】:

    • @Afshin at point 5 > “在自定义表单中,您可以在将新用户实例保存到数据库之前访问它”- 您的意思是在这里使用信号吗?
    【解决方案2】:

    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 激活它们。

    【讨论】:

    • 我并不想变得困难或挑剔,我真的很想知道......引用“私人”财产不被认为是不好的做法吗?在这种情况下,_state。我知道“_”只是python中的一个约定,而不是真正的私有属性,但我认为基本规则是任何“私有”属性(或方法)都可能在后续更新中发生变化,所以最好不要依赖它们。
    • 我不能声称在这里避免了不好的做法。我需要这个功能,这是对我有用的方法。很可能在更新后,对 _state 属性的检查有时会失败。理想情况下,我会找到另一种方法。但这已经生产多年了,我认为最好不要弄乱它。谢谢你指出。如果它发生,这将使我更有可能找到故障点。 :-)
    【解决方案3】:
    1. 避免修改内置函数。有更好的方法来做事。
    2. 喜欢signals。信号很棒。
    3. 在这种情况下,我将附加到django.contrib.auth.models.User 的pre_save 信号,并手动更正模型实例的is_active 属性(如果对象是新的)。
    4. 这样,您可以添加一些逻辑来确保正确地将用户标记为非活动用户。
    5. 因为在管理员中添加的用户应该是活跃的,如果管理员将他们标记为活跃的话。

    【讨论】:

    • 太酷了.. 所以我必须操纵 django-social-auth 包来添加信号...对吗?
    • 并非如此。您可以从 Django 项目中的任何应用程序中执行此操作。如果可以的话,应该避免修补软件包。
    • 如何检查用户是否正在创建,而不仅仅是被修改?
    猜你喜欢
    • 2016-09-05
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多