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

Django allauth中password_set信号失效问题求助

Fix: Django password_set Signal Not Triggering for Custom Password Set View

Hey there, let's figure out why your password_set signal isn't firing and how to get that post-password-set login redirect working.

First, the core issue: Django's built-in password_set signal only gets sent when you use Django's official password-setting views (like SetPasswordView). Since you've written a custom setPassword view that calls user.set_password() and user.save() manually, Django won't automatically send that signal for you. On top of that, your signal receiver function had the wrong parameter order, which would have prevented it from running even if the signal was sent.

Let's break down the fixes:

Option 1: Manually Send the password_set Signal

If you want to keep using the signal approach, you need to trigger the signal yourself after saving the new password in your view. Also, fix the receiver's parameter order to match what the signal expects.

Updated views.py:

from django.contrib.auth.signals import password_set
from django.dispatch import receiver
from django.http import JsonResponse
from django.contrib.auth.models import User
from .models import Profile
from django.core.exceptions import ImmediateHttpResponse
from django.shortcuts import render
from django.contrib.auth import logout

@receiver(user_logged_in)
def getFirstTimePass(user, request, **kwargs): # This works as expected
    if user.profile.provider != '' and user.profile.firstTimeLogin:
        user.profile.firstTimeLogin = False
        user.profile.save()
        raise ImmediateHttpResponse(render(request, 'index.html', {'type': user.profile.provider, 'email': user.email}))

# Fixed receiver parameter order: sender first, then user, then request
@receiver(password_set)
def loginAfterPassChange(sender, user, request=None, **kwargs):
    print("Signal triggered! 🎉") # Test if this prints in your console
    # Store a message in session to pass to frontend
    request.session['post_password_msg'] = 'Please login with your new password.'

def setPassword(request):
    data = {'errMsg': 'Something went wrong.'}
    if not request.user.has_usable_password():
        password = request.POST.get('password')
        request.user.set_password(password)
        request.user.save()
        # Manually send the password_set signal
        password_set.send(sender=User, user=request.user, request=request)
        # Optional: Log the user out immediately (Django doesn't do this automatically)
        logout(request)
        data['errMsg'] = ''
        data['redirect_to_login'] = True
    return JsonResponse(data)

Option 2: Handle Logic Directly in the View (Simpler!)

Signals can add unnecessary complexity here. Since you already control the password-setting flow in your custom view, just handle the login prompt/redirect logic directly there. This is more straightforward and avoids signal-related bugs.

Updated setPassword view:

from django.contrib.auth import logout

def setPassword(request):
    data = {'errMsg': 'Something went wrong.'}
    if not request.user.has_usable_password():
        password = request.POST.get('password')
        request.user.set_password(password)
        request.user.save()
        # Log the user out so they have to re-login with the new password
        logout(request)
        data['errMsg'] = ''
        # Send data to frontend to trigger login dialog
        data['msg'] = 'Please login with your new password.'
        data['redirect_to_login'] = True
    return JsonResponse(data)

Then, in your frontend code, check for redirect_to_login: true in the response and show the login dialog or redirect to your login page.

Key Notes to Remember

  1. Django doesn't auto-log users out after set_password(): You have to call logout(request) manually if you want the user to re-authenticate with their new password.
  2. Signal parameter order matters: The password_set signal sends sender, user, and request (optional) in that order. Your original receiver had request first, which meant it couldn't match the signal's arguments.
  3. Signals vs direct view logic: For simple post-action tasks like this, handling it directly in the view is usually better—it's easier to debug and maintain.

Either of these approaches should get your post-password-set login prompt working correctly.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:35:55