如何在管理面板中检查django员工用户的首次登录?

Moh*_*han 5 python django django-admin

我正在执行django项目,并且正在使用默认的auth应用进行身份验证。
我知道last_login用户模型中有一个字段,用于存储用户的上次登录时间。

当职员用户首次登录到管理面板时,我想检查该last_login字段是否为None并将其重定向到更改密码页面。

我应该把这张支票放在哪里?


到目前为止我尝试过的是:

我尝试使用自定义登录表单并覆盖其默认confirm_login_allowed方法,但看来我只能提出验证错误以阻止使用这些表单的登录尝试。

我也尝试使用django.contrib.auth.signals.user_logged_inSignal,但也不允许在last_loginis 时返回重定向响应None

我想知道在验证用户身份后如何返回重定向响应。

Raj*_*mon 5

使用自定义 Django 管理员AdminSite并使用 login_form 属性为管理员登录页面提供自定义登录表单。

管理文件

class MyAdminSite(AdminSite):
    login_form = CustomAdminLoginForm

admin_site = MyAdminSite(name='myadmin')
admin_site.register(User)
admin_site.register(Group
Run Code Online (Sandbox Code Playgroud)

网址.py

当覆盖 Admin 时,我们必须摆脱 Django 默认的 admin

from app.admin import admin_site

url(r'^admin/', admin_site.urls)
Run Code Online (Sandbox Code Playgroud)

表格.py

AuthenticationFormconfirm_login_allowed方法使用它来授予登录或不登录的权限。

class CustomAdminLoginForm(AuthenticationForm):
    def confirm_login_allowed(self, user):
        if user.last_login:
            raise ValidationError(mark_safe('Hey first time user please reset your password here... <a href="/test">test</a>'), code='inactive')
Run Code Online (Sandbox Code Playgroud)

注意:对于这种方法,您必须考虑很多边缘情况。

  1. 如果用户第一次没有设置密码,你将如何处理第二次尝试呢?这次 last_long 不是 None。虽然date_joined来救援。last_login == date_joined
  2. 但是如果用户第一天没有设置密码,第二天又来了怎么办?

编辑:

您可以使用信号来检查登录用户并在config_login_allowed此处应用逻辑......?

from django.contrib.auth.signals import user_logged_in


def change_password_first_time(sender, user, request, **kwargs):
    # Your business logic here...

user_logged_in.connect(change_password_first_time)
Run Code Online (Sandbox Code Playgroud)


Arm*_*ani 4

Django 管理不是那么可配置。您应该了解其内部视图。登录/注销视图位于 DjangoAdminSite类内部(您通常通过 Django 类访问admin.site)。我的实现有点hacky但很小:

粘贴在顶部urls.py

from django.contrib import admin
from django.contrib.admin import AdminSite
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect

class MyAdminSite(AdminSite):
    def login(self, request, extra_context=None):
        new_user = False
        user = None

        username = request.POST.get('username')  # Hack to find user before its last_login set to now.
        if username:
            user = User.objects.filter(username=username).first()
            if user:
                new_user = user.last_login is None

        r = super(MyAdminSite, self).login(request, extra_context)

        if new_user and request.user == user and isinstance(r, HttpResponseRedirect):  # Successful logins will result in a redirect.
            return HttpResponseRedirect(reverse('admin:password_change'))
        return r

admin.site = MyAdminSite()
Run Code Online (Sandbox Code Playgroud)

如果您想要一个更干净的解决方案,我建议在用户模型内部使用布尔值而不是依赖,last_login这样您就可以检查request.user而不是我侵入request.POST.

您可以阅读AdminSite.logindjango.contrib.auth.views.login了解 Django 内部实际发生的情况。