无法使用自定义用户模型在 Django 中更改密码

问题描述 投票:0回答:2

我一直在尝试让默认的 Django 身份验证系统与自定义用户一起使用。我能够创建用户类型、登录和注销。但是,当涉及到更改密码时,我会注销,然后密码就不会更改。我还尝试查看通过电子邮件重置密码是否会改变任何内容,但我仍然无法更改密码。我的应用程序名称是帐户。

这是我的自定义用户模型,我尝试添加 set_password 方法以确保它可以更改密码。我仅包含用户管理器以提高可读性:

class UserManager(BaseUserManager):
    def _create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError("The given email must be set")
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", False)
        extra_fields.setdefault("is_superuser", False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)

        if extra_fields.get("is_staff") is not True:
            raise ValueError("Superuser must have is_staff=True.")
        if extra_fields.get("is_superuser") is not True:
            raise ValueError("Superuser must have is_superuser=True.")

        return self._create_user(email, password, **extra_fields)

class CustomUser(AbstractUser):
    username = None
    email = models.EmailField(_("email address"), unique=True)
    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []
    objects = UserManager()

    def set_password(self, raw_password):
        self.password = make_password(raw_password)
        self._password = raw_password


class Student(CustomUser):
    student = StudentManager()

    class Meta:
        proxy = True


class Teacher(CustomUser):
    teacher = TeacherManager()

    class Meta:
        proxy = True

对于其余的,我使用所有默认的 Django 身份验证 URL 和视图,但我尝试修改密码更改视图以确保我不会注销,但问题仍然存在:

urlpatterns = [
    path('password_change/', CustomPasswordChangeView.as_view(), name='password_change')
    path('', include('django.contrib.auth.urls')),   
]

自定义密码更改视图:

class CustomPasswordChangeView(auth.views.PasswordChangeView):
    template_name = "registration/password_change_form.html"
    success_url = reverse_lazy("password_change_done")

    def form_valid(self, form):
        response = super().form_valid(form)
        update_session_auth_hash(self.request, form.user)
        return response

即使更改了form_valid方法,提交表单时我仍然处于注销状态。我输入旧的电子邮件和密码,然后被重定向到password_change_done视图,并且密码没有更改。

最后,我确保将以下内容添加到设置中: AUTH_USER_MODEL = "帐户.自定义用户"

python django authentication django-authentication django-users
2个回答
1
投票

在评论告诉我问题无法重现后,我发现了问题:我没有包含在问题中的保存功能。

    def save(self, *args, **kwargs):
    if not self.pk:
        super().save(*args, **kwargs)
        try:
            self.base_group.user_set.add(self)
        except:
            pass

这本应确保用户始终属于正确的组,但它会干扰密码更改。感谢所有评论和回复的人。


0
投票

看来您已经在 Django 中正确定义了自定义用户模型,并实现了自定义密码更改视图。但是,您可以进行一些修改,以确保密码更改过程按预期进行。

  1. 删除 CustomUser 模型中的 set_password 方法: 您在 CustomUser 模型中实现的 set_password 方法是不必要的,因为 Django 的内置 AbstractBaseUser 类已经提供了 set_password 方法。通过在自定义用户模型中覆盖它,您可能会引入意想不到的行为。从 CustomUser 模型中删除 set_password 方法。
  2. 直接使用Django内置的PasswordChangeView: 您可以直接在 URL 配置中使用 Django 的内置 PasswordChangeView,而不是创建自定义密码更改视图。删除 CustomPasswordChangeView 并更新您的 urls.py 文件,如下所示:
from django.contrib.auth import views as auth_views

urlpatterns = [
    path('password_change/', auth_views.PasswordChangeView.as_view(template_name="registration/password_change_form.html", success_url=reverse_lazy("password_change_done")), name='password_change'),
    path('password_change_done/', auth_views.PasswordChangeDoneView.as_view(template_name="registration/password_change_done.html"), name='password_change_done'),
    # Other authentication URLs
]
  1. 确保 URL 模式正确: 确保您已在项目的 urls.py 文件中正确包含身份验证 URL。确认 urlpatterns 列表包含 password_change_done 视图的路径,如上面的示例所示。
  2. 检查您的注册/password_change_form.html 模板: 确保您的password_change_form.html模板中的表单正确提交了旧密码、新密码和确认信息。确保表单字段的命名正确(old_password、new_password1、new_password2)以匹配 Django 的默认行为。

进行这些修改后,再次尝试密码更改过程,看看问题是否得到解决。

© www.soinside.com 2019 - 2024. All rights reserved.