Django:通过信号获取IP地址

0 投票
4 回答
1639 浏览
提问于 2025-04-16 08:10

我想记录试图登录的用户的IP地址,打算用信号来实现。请问我该怎么做呢?

我已经记录下了登录的时间。

#models.py
class UserLogin(models.Model):
    """user details when logging in"""        
    user        = models.ForeignKey(User)
    timestamp   = models.DateTimeField(auto_now=True)

这是信号的部分:

#models.py
def user_login_save(sender, instance, **kwargs):
if instance.last_login:
    old = instance.__class__.objects.get(pk=instance.pk)
    if instance.last_login != old.last_login:
        instance.userlogin_set.create(timestamp=instance.last_login)

models.signals.post_save.connect(user_login_save,  sender=User)

虽然我知道可以通过:request.META[REMOTE_ADDR]来获取IP地址,但我的问题是我在模型里不能使用request这个实例。我也不太确定从请求中获取信息是否是个好习惯。

那么,有什么推荐的方法吗?

任何回复我都会非常感激。

祝好,

Wenbert

4 个回答

1

这个问题很老了,但我今天遇到了同样的问题,而这是我在谷歌上找到的第一个结果。所以也许这对其他人也有帮助。这就是我解决这个问题的方法。

from django.contrib.auth.signals import (
    user_logged_in,
    user_logged_out,
    user_login_failed,
)
from django.dispatch import receiver
import logging

user_logger = logging.getLogger("user")

@receiver(user_logged_in)
def log_user_login(sender, user, **kwargs):
    """log user "login" to log-file setup in django settings.py"""
    # if the IP-ADRESS is 127.0.0.1 from external users then check this     
    # https://stackoverflow.com/questions/4581789/how-do-i-get-user-ip-address-in-django
    request = kwargs["request"]
    ip_address = request.META.get("REMOTE_ADDR")
    user_logger.info(f"{user} login successful. IP-Address: {ip_address}")

# other functions deleted for brevity
1

因为这个实例在信号中被传递,而这个实例实际上就是保存下来的那个对象,所以你可以在保存的时候把请求对象或者IP地址附加到这个实例上。

user_login.request=request
user_login.save()

然后在信号中可以像这样获取它:

instance.request
1

虽然我知道怎么通过:request.META[REMOTE_ADDR] 获取IP地址,但我的问题是我在模型里不能使用request实例。

这就是为什么你需要视图函数的原因。

我也不太确定从请求中获取东西是否是个好做法。

这是完全可以的。

  • 这就是为什么每个视图函数都会提供请求的原因。

  • 这就是你需要视图函数的原因。

只需在视图函数中处理这些。除非你在写一种新的数据库接口,否则不要去碰信号。

撰写回答