在Django中获取当前用户登录信号

时间:2011-01-18 08:09:08

标签: django django-admin django-users

我只是在Django中使用管理站点。我有2个Django信号(pre_save和post_save)。我想拥有当前用户的用户名。我该怎么办?我似乎无法发送请求或者我不理解它。

由于

6 个答案:

答案 0 :(得分:19)

我不愿意处理线程本地状态,我决定尝试不同的方法。据我所知,post_savepre_save信号处理程序在调用save()的线程中同步调用。如果我们处于正常的请求处理循环中,那么我们可以沿着堆栈向上查找请求对象作为局部变量。 e.g。

from django.db.models.signals import pre_save
from django.dispatch import receiver

@receiver(pre_save)
def my_callback(sender, **kwargs):
    import inspect
    for frame_record in inspect.stack():
        if frame_record[3]=='get_response':
            request = frame_record[0].f_locals['request']
            break
    else:
        request = None
    ...

如果有当前请求,您可以从中获取user属性。

注意:就像它在inspect模块文档中所述,

  

此函数依赖于解释器中的Python堆栈框架支持,而不是   保证存在于Python的所有实现中。

答案 1 :(得分:10)

如果您使用的是管理网站,为什么不使用自定义模型管理员

class MyModelAdmin( admin.ModelAdmin ):
    def save_model( self, request, obj, form, change ):
        #pre save stuff here
        obj.save()
        #post save stuff here



admin.site.register( MyModel, MyModelAdmin )

每次保存对象时都会触发信号,无论是由管理员执行还是某些与请求无关的进程完成,并且实际上不是基于请求执行的适当位置操作

答案 2 :(得分:1)

您可以使用中间件存储当前用户:http://djangosnippets.org/snippets/2179/

然后您就可以通过get_current_user()

获取用户

答案 3 :(得分:0)

在两个信号中,信号发送三个参数,

  • 汇款人
  • 实例
  • 使用

你需要的是即时修改......

def signal_catcher(sender, instance, **kwargs):
    uname = instance.username

http://docs.djangoproject.com/en/dev/ref/signals/#pre-save

答案 4 :(得分:0)

我们可以使用中间件类来解决这个问题。 在将存储用户变量的位置创建单例类。

class Singleton(type):
    '''
        Singleton pattern requires for GetUser class
    '''
    def __init__(cls, name, bases, dicts):
        cls.instance = None

    def __call__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls.instance 


class NotLoggedInUserException(Exception):
    '''
    '''
    def __init__(self, val='No users have been logged in'):
        self.val = val
        super(NotLoggedInUser, self).__init__()

    def __str__(self):
        return self.val

class LoggedInUser(object):
    __metaclass__ = Singleton

    user = None

    def set_user(self, request):
        if request.user.is_authenticated():
            self.user = request.user

    @property
    def current_user(self):
        '''
            Return current user or raise Exception
        '''
        if self.user is None:
            raise NotLoggedInUserException()
        return self.user

    @property
    def have_user(self):
    return not user is None

创建自己的中间件类,为LoggedInUser实例设置用户,并在settings.py

中的'django.contrib.auth.middleware.AuthenticationMiddleware'之后插入中间件
from useranytimeaccess import LoggedInUser
class LoggedInUserMiddleware(object):
    '''
        Insert this middleware after django.contrib.auth.middleware.AuthenticationMiddleware
    '''
    def process_request(self, request):
        '''
            Returned None for continue request
        '''
        logged_in_user = LoggedInUser()
        logged_in_user.set_user(request)
        return None

在信号中导入LoggedInUser类并获取当前用户

logged_in = LoggedInUser()
user = logged_in.user

答案 5 :(得分:0)

没有黑客攻击:在用户登录/注销时使用信号来记住登录者,对于Django测试框架,只要您连接并调用该信号,这也将起作用:

current_user = None

@receiver(user_logged_in, sender=User)
def user_logged_in(sender, request, user, **kwargs):
    global current_user
    current_user = user

@receiver(user_logged_out, sender=User)
def user_logged_out(sender, request, user, **kwargs):
    global current_user
    current_user = None

@receiver(post_save, sender=StatusHistory)
def status_history_post_save(sender, instance: StatusHistory,
                             created, **kwargs):
    global current_user
    if current_user is None or instance is None or instance.shipment is None:
        return
    # ok if we here -> user is connected, keep on:
    # .........
    # blabla
    # .........