在Django管理界面

时间:2018-06-15 15:44:52

标签: python django django-admin django-validation

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

  

默认情况下,验证程序在表单中用于重置或更改密码以及createsuperuser和changepassword管理命令。验证程序不在模型级别应用,例如在User.objects.create_user()和create_superuser()中,因为我们假设开发人员而不是用户在该级别与Django交互,并且因为模型验证不会自动运行作为创建模型的一部分。

但在我的Django应用程序中,我只使用Django Admin界面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',
    }

2 个答案:

答案 0 :(得分:1)

您链接的文档说:

  

默认情况下,表单中使用验证器来重置或更改密码

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

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

仔细考虑是否真的需要覆盖AbstractBaseUser。如果您改写AbstractUser,那么使用/扩展内置表单/模型管理员会更容易,而且您不必自己实施密码验证。

答案 1 :(得分:0)

来自问题作者的UPD:
对于遇到相同问题的每个人:您需要将该功能添加到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)