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
相关产品推荐
相关产品推荐

