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

关于在Django Admin中实现用户登录登出时间自动记录的可行性问询

解决Django Admin考勤式登录登出记录问题

嘿,你当前的UserLogs模型有个核心问题——用了OneToOneField(User),这就导致每个用户只能有一条登录记录,完全不符合你「每次登录都新增独立记录」的需求。咱们一步步来调整,配合Django的信号机制就能实现你想要的考勤功能。

第一步:重构UserLogs模型

把OneToOneField换成ForeignKey,这样一个用户就能关联多条登录日志了:

from django.db import models
from django.contrib.auth.models import User
from django.utils.timezone import now

class UserLogs(models.Model):
    user = models.ForeignKey(User, related_name="login_logs", on_delete=models.CASCADE)
    time_in = models.DateTimeField(default=now)
    time_out = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return f"{self.user.username} - 登录于 {self.time_in}"

这里把related_name改成login_logs更贴合语义,之后查询用户的所有登录记录也更方便。

第二步:用Django信号自动记录登录/登出

Django内置了用户登录和登出的信号,咱们用它来自动创建和更新日志:

在你的app目录下新建signals.py文件,写入以下代码:

from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
from django.utils.timezone import now
from .models import UserLogs

# 用户登录Admin时创建新的登录记录
@receiver(user_logged_in)
def create_login_log(sender, request, user, **kwargs):
    # 只捕获Admin登录的情况(如果不需要区分前台/Admin,可以去掉这个判断)
    if request.path.startswith('/admin/'):
        UserLogs.objects.create(user=user)

# 用户登出Admin时更新对应记录的登出时间
@receiver(user_logged_out)
def update_logout_time(sender, request, user, **kwargs):
    if request.path.startswith('/admin/'):
        # 找到该用户最近的、还没记录登出时间的登录记录
        latest_unfinished_log = UserLogs.objects.filter(
            user=user, 
            time_out__isnull=True
        ).order_by('-time_in').first()
        
        if latest_unfinished_log:
            latest_unfinished_log.time_out = now()
            latest_unfinished_log.save()

接下来要确保Django启动时能加载这些信号,在app的apps.py里修改:

from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app_name'  # 替换成你的app名称

    def ready(self):
        import your_app_name.signals  # 导入信号模块

额外优化建议

  • 如果用户直接关闭浏览器没点登出,这条记录的time_out会一直为空。你可以加个定时任务(比如用Celery),把超过一定时间未登出的记录自动填充超时时间。
  • 可以在Admin后台注册UserLogs模型,方便查看和管理考勤记录:
from django.contrib import admin
from .models import UserLogs

class UserLogsAdmin(admin.ModelAdmin):
    list_display = ('user', 'time_in', 'time_out')
    list_filter = ('user', 'time_in')
    search_fields = ('user__username',)

admin.site.register(UserLogs, UserLogsAdmin)

这样改完之后,每次员工登录Django Admin都会新增一条独立的登录记录,点击登出时会自动更新对应记录的登出时间,完美实现你要的考勤功能~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 00:47:37