【问题标题】:Django Custom Authentication - BaseUserManager's create_user not being usedDjango 自定义身份验证 - 未使用 BaseUserManager 的 create_user
【发布时间】:2015-09-18 18:13:39
【问题描述】:

我自定义了 Django 的身份验证,现在每次我尝试使用 Django Admin 创建一个新用户时,这个用户的密码都会直接保存,而不是经过哈希处理。我发现未调用 BaseUserManager 类的 create_user 方法。当我使用 bash 创建超级用户时,它已正确完成。我的模型有什么问题吗?

settings.py

AUTH_USER_MODEL = 'authentication.BaseAccount'

apps/authentication/models.py

class BaseAccountManager(BaseUserManager):
   def create_user(self, email, password=None, **kwargs):
      if not email:
          raise ValueError('Users must have a valid email address.')

      account = self.model(
        email=self.normalize_email(email)
      )
      account.set_password(password)
      account.save()

   return account

   def create_superuser(self, email, password, **kwargs):
      account = self.create_user(email, password, **kwargs)

      account.is_admin = True
      account.is_staff = True
      account.save()

   return account

class BaseAccount(AbstractBaseUser):
   email = models.EmailField(unique=True)

   first_name = models.CharField(max_length=40, blank=True)
   last_name = models.CharField(max_length=40, blank=True)

   is_admin = models.BooleanField(default=False)
   is_staff = models.BooleanField(default=False)

   created_at = models.DateTimeField(auto_now_add=True)
   updated_at = models.DateTimeField(auto_now=True)

   objects = BaseAccountManager()

   USERNAME_FIELD = 'email'

   def __unicode__(self):
      return self.email

   def get_full_name(self):
      return ' '.join([self.first_name, self.last_name])

   def get_short_name(self):
      return self.first_name

   def has_perm(self, perm, obj=None):
      return self.is_admin

   def has_module_perms(self, app_label):
      return self.is_admin

【问题讨论】:

  • 听起来您的模型管理员可能继承自 ModelAdmin,因此缺少正确设置密码的代码。

标签: python django authentication


【解决方案1】:

对于未来的读者,因为这个问题也让我撞到了墙上......

要从您的 django 项目中的任何位置访问宝贵的 create_user() 方法:

from django.contrib.auth import get_user_model

class SomeClass():
    # This could be a form, for example...
    def some_function():
        get_user_model().objects.create_user()

如果你从某个自定义表单的save()方法调用它,请妥善保管commit参数,不要忘记在settings.py文件中注册你的自定义用户模型,按照Django documentation.

【讨论】:

    【解决方案2】:

    我找到了有关密码的问题的答案,但我仍然不知道如何正确调用 create_user 函数。该示例删除了用户名,仅支持电子邮件。我仍在寻找一种方法来从 BaseUserManager 中获取自定义 UserManager 中定义的 create_user 函数。我的自定义管理器发送一封带有密码重置链接和一次性令牌的电子邮件......这将避免需要从 django admin 实际设置散列密码。

    https://www.caktusgroup.com/blog/2013/08/07/migrating-custom-user-model-django/

    首先创建您自己的表单:

    # appname/forms.py
    
    from django.contrib.auth.forms import UserCreationForm, UserChangeForm
    
    from appname.models import CustomUser
    
    class CustomUserCreationForm(UserCreationForm):
        """
        A form that creates a user, with no privileges, from the given email and
        password.
        """
    
        def __init__(self, *args, **kargs):
            super(CustomUserCreationForm, self).__init__(*args, **kargs)
            del self.fields['username']
    
        class Meta:
            model = CustomUser
            fields = ("email",)
    
    class CustomUserChangeForm(UserChangeForm):
        """A form for updating users. Includes all the fields on
        the user, but replaces the password field with admin's
        password hash display field.
        """
    
        def __init__(self, *args, **kargs):
            super(CustomUserChangeForm, self).__init__(*args, **kargs)
            del self.fields['username']
    
        class Meta:
            model = CustomUser
    

    然后使用这些形式:

    # appname/admin.py
    
    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin
    from django.utils.translation import ugettext_lazy as _
    
    from appname.models import CustomUser
    from appname.forms import CustomUserChangeForm, CustomUserCreationForm
    
    class CustomUserAdmin(UserAdmin):
        # The forms to add and change user instances
    
        # The fields to be used in displaying the User model.
        # These override the definitions on the base UserAdmin
        # that reference the removed 'username' field
        fieldsets = (
            (None, {'fields': ('email', 'password')}),
            (_('Personal info'), {'fields': ('first_name', 'last_name')}),
            (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
                                           'groups', 'user_permissions')}),
            (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
        )
        add_fieldsets = (
            (None, {
                'classes': ('wide',),
                'fields': ('email', 'password1', 'password2')}
            ),
        )
        form = CustomUserChangeForm
        add_form = CustomUserCreationForm
        list_display = ('email', 'first_name', 'last_name', 'is_staff')
        search_fields = ('email', 'first_name', 'last_name')
        ordering = ('email',)
    
    admin.site.register(CustomUser, CustomUserAdmin)
    

    【讨论】:

    • 示例中的 PermissionsMixin 也很有帮助
    猜你喜欢
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    • 1970-01-01
    • 2015-11-12
    • 2013-11-19
    相关资源
    最近更新 更多