在 Django 管理界面中验证新用户密码

Validate new users passwords in Django admin interface

Django documentation 中有一个有趣的时刻:

By default, validators are used in the forms to reset or change passwords and in the createsuperuser and changepassword management commands. Validators aren’t applied at the model level, for example in User.objects.create_user() and create_superuser(), because we assume that developers, not users, interact with Django at that level and also because model validation doesn’t automatically run as part of creating models.

但是在我的 Django 应用程序中,我只使用 Django 管理界面 admin.ModelAdmin
当我尝试创建新用户时,我可以破坏 AUTH_PASSWORD_VALIDATORS.
中的所有验证器 如何使用验证器 AUTH_PASSWORD_VALIDATORS 在 Django 管理界面中创建新用户时验证密码?

admin.py:

class UserCreateForm(ModelForm):
class Meta:
    model = User
    fields = ['username', 'password']


class UserAdmin(admin.ModelAdmin):
    form = UserCreateForm
    list_display = ('username')

    def get_form(self, request, obj=None, change=False, **kwargs):
        if change:
            return self.change_form
        return super(UserAdmin, self).get_form(request, obj, **kwargs)

    def has_add_permission(self, request):
        return True

    def has_delete_permission(self, request, obj=None):
        return False

    def has_change_permission(self, request, obj=None):
        return True

    def save_model(self, request, obj, form, change):
        if obj.pk:
            orig_obj = User.objects.get(pk=obj.pk)
            if obj.password != orig_obj.password:
                obj.set_password(obj.password)
        else:
            obj.is_superuser = True
            obj.set_password(obj.password)
        obj.save()

models.py:

class User(AbstractBaseUser, PermissionsMixin):
    USERNAME_FIELD = 'username'
    username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        max_length=150,
        unique=True,
        validators=[username_validator]
        )

    objects = UserManager()

managers.py:

class UserManager(BaseUserManager):
    def create_user(self, username, password=None):
        if not username:
            raise ValueError('Users must have username assigned')
        user = self.model(username=username)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, password=None):
        user = self.create_user(username, password=password)
        user.is_superuser = True
        user.save(using=self._db)
        return user

settings.py:

AUTH_USER_MODEL = 'users.User'
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    }

您链接的文档说:

By default, validators are used in the forms to reset or change passwords

例如,UserAdmin 使用 UserCreationForm 来验证密码。

您有自己的 UserAdminUserCreateForm,因此除非您添加此功能,否则不会验证密码。

仔细考虑是否真的需要覆盖AbstractBaseUser。如果您改写 AbstractUser,那么 use/extend 内置 forms/model 管理员会更容易,并且您不必自己实施密码验证。

来自问题作者的更新:
对于遇到同样问题的每个人:您需要将该功能添加到 UserCreateForm

def clean(self):
    password = self.cleaned_data.get('password')
    if password:
        try:
            password_validation.validate_password(password, self.instance)
        except forms.ValidationError as error:
            self.add_error('password', error)