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

Django 4中UserAdmin的save_model修改密码时未触发问题

解决Django后台修改用户密码时save_model不触发的问题

问题根源

Django Admin里的用户密码修改页面是独立模块,它走的是user_change_password专属视图,而非常规的模型保存流程,所以你重写的save_model方法根本不会被调用。

两种可行解决方案

方案一:重写changeform_view拦截密码修改请求

直接在自定义UserAdmin里拦截密码修改的POST请求,完成密码修改后清理用户会话:

from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
from django.contrib import admin
from django.contrib.auth import update_session_auth_hash
from django.contrib.sessions.models import Session

@admin.register(User)
class UserAdmin(BaseUserAdmin):
    def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
        # 判断是否是密码修改提交
        if request.method == 'POST' and '_password' in request.POST:
            user = User.objects.get(pk=object_id)
            # 删除该用户的所有活跃会话
            sessions = Session.objects.filter(session_data__contains=f'"_auth_user_id": "{user.pk}"')
            sessions.delete()
            # 如果修改的是当前管理员自己的密码,要更新会话哈希避免被登出
            if user == request.user:
                update_session_auth_hash(request, user)
        return super().changeform_view(request, object_id, form_url, extra_context)

方案二:监听user_password_changed信号

Django在用户密码修改完成后会发送user_password_changed信号,通过监听这个信号来自动清理会话:

from django.contrib.auth.signals import user_password_changed
from django.contrib.sessions.models import Session
from django.dispatch import receiver

@receiver(user_password_changed)
def invalidate_user_sessions(sender, user, **kwargs):
    # 清除该用户的所有会话
    sessions = Session.objects.filter(session_data__contains=f'"_auth_user_id": "{user.pk}"')
    sessions.delete()

把这段代码放在admin.py里即可,要是单独放signals.py,记得在apps.py的ready方法里导入信号确保生效。

注意点

  • 用信号方案时,要确认信号被正确注册,别因为导入顺序问题导致没触发。
  • 修改自己密码的管理员,必须调用update_session_auth_hash,不然会被直接踢下线。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:33:12