You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dj_rest_auth自定义密码重置序列化器未生效问题求助

自定义密码重置序列化器未加载的问题排查

问题概述

已配置自定义密码重置序列化器,但系统未加载该自定义逻辑。使用版本:dj-rest-auth4.0.1,django-allauth0.54.0。

实现代码

accounts/urls.py

from django.urls import include, path
from .views import check_user_email
from dj_rest_auth.views import PasswordResetConfirmView, PasswordResetView
from django.views.generic import TemplateView

urlpatterns = [
    path(
        "password/reset/confirm/<slug:uidb64>/<slug:token>/",
        PasswordResetConfirmView.as_view(),
        name="password_reset_confirm",
    ),
    path("", include("dj_rest_auth.urls")),
    # path("registration/", include("dj_rest_auth.registration.urls")),
    path("check-user-email/", check_user_email),
]

accounts/serializer.py

from allauth.account.utils import (
    filter_users_by_email,
    user_pk_to_url_str,
    user_username,
)
from allauth.utils import build_absolute_uri
from django.contrib.sites.shortcuts import get_current_site
from allauth.account.adapter import get_adapter
from allauth.account.forms import default_token_generator
from allauth.account import app_settings
from dj_rest_auth.forms import AllAuthPasswordResetForm
from dj_rest_auth.serializers import PasswordResetSerializer
from rest_framework import serializers


class CustomAllAuthPasswordResetForm(AllAuthPasswordResetForm):
    def clean_email(self):
        """
        Invalid email should not raise error, as this would leak users
        for unit test: test_password_reset_with_invalid_email
        """
        email = self.cleaned_data["email"]
        email = get_adapter().clean_email(email)
        self.users = filter_users_by_email(email, is_active=True)
        return self.cleaned_data["email"]

    def save(self, request, **kwargs):
        current_site = get_current_site(request)
        email = self.cleaned_data["email"]
        token_generator = kwargs.get("token_generator", default_token_generator)

        for user in self.users:
            temp_key = token_generator.make_token(user)

            path = f"I basically want to add frontend url here/{user_pk_to_url_str(user)}/{temp_key}/"
            url = build_absolute_uri(request, path)
            # Values which are passed to password_reset_key_message.txt
            context = {
                "current_site": current_site,
                "user": user,
                "password_reset_url": url,
                "request": request,
                "path": path,
            }

            if (
                app_settings.AUTHENTICATION_METHOD
                != app_settings.AuthenticationMethod.EMAIL
            ):
                context["username"] = user_username(user)
            get_adapter(request).send_mail(
                "account/email/password_reset_key", email, context
            )

        return self.cleaned_data["email"]


class MyPasswordResetSerializer(PasswordResetSerializer):
    def validate_email(self, value):
        # use the custom reset form
        self.reset_form = CustomAllAuthPasswordResetForm(data=self.initial_data)
        if not self.reset_form.is_valid():
            raise serializers.ValidationError(self.reset_form.errors)

        return value

settings.py(关键配置片段)

REST_AUTH_SERIALIZERS = {
    "PASSWORD_RESET_SERIALIZER": "accounts.serializers.MyPasswordResetSerializer",
}

REST_AUTH = {
    "USE_JWT": True,
    "JWT_AUTH_COOKIE": "jwt-auth",
    "JWT_AUTH_REFRESH_COOKIE": "jwt-refresh",
    "JWT_AUTH_SECURE": isProd,
}

问题原因及修复方案

1. 模块路径错误(核心原因)

序列化器文件名为serializer.py(单数),但settings.py中配置的路径是复数形式accounts.serializers.MyPasswordResetSerializer,导致Django无法找到自定义序列化器,直接使用默认实现。

修复:
修改settings.py中的序列化器路径:

REST_AUTH_SERIALIZERS = {
    "PASSWORD_RESET_SERIALIZER": "accounts.serializer.MyPasswordResetSerializer",
}

2. 路由优先级与视图配置问题

默认的dj_rest_auth.urls加载的PasswordResetView未自动读取REST_AUTH_SERIALIZERS配置,需要手动指定自定义序列化器。

修复:
在accounts/urls.py中添加自定义密码重置路由,放在include("dj_rest_auth.urls")之前确保优先匹配:

from django.urls import include, path
from .views import check_user_email
from dj_rest_auth.views import PasswordResetConfirmView, PasswordResetView
from .serializer import MyPasswordResetSerializer

urlpatterns = [
    path(
        "password/reset/confirm/<slug:uidb64>/<slug:token>/",
        PasswordResetConfirmView.as_view(),
        name="password_reset_confirm",
    ),
    # 自定义密码重置路由,指定序列化器
    path("password/reset/", PasswordResetView.as_view(serializer_class=MyPasswordResetSerializer), name="rest_password_reset"),
    path("", include("dj_rest_auth.urls")),
    path("check-user-email/", check_user_email),
]

3. 可选:重写视图确保适配

若上述修改仍未生效,可直接重写PasswordResetView:

# accounts/views.py
from dj_rest_auth.views import PasswordResetView
from .serializer import MyPasswordResetSerializer

class CustomPasswordResetView(PasswordResetView):
    serializer_class = MyPasswordResetSerializer

然后在urls.py中替换路由:

path("password/reset/", CustomPasswordResetView.as_view(), name="rest_password_reset"),

内容的提问来源于stack exchange,提问作者Shahriar Dhruvo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 05:25:57