Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Django中获取当前用户登录信号_Django_Django Admin_Django Users - Fatal编程技术网

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

在Django中获取当前用户登录信号,django,django-admin,django-users,Django,Django Admin,Django Users,我只是在使用Django中的管理站点。我有两个Django信号(pre_save和post_save)。我想知道当前用户的用户名。我该怎么做?似乎我无法发送请求,或者我不理解 谢谢两个信号,信号发送三个参数 寄件人 实例 使用 你需要的是即时修改 def signal_catcher(sender, instance, **kwargs): uname = instance.username 您可以使用中间件存储当前用户: 然后,您可以使用get\u current\u user(

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


谢谢两个信号,信号发送三个参数

  • 寄件人
  • 实例
  • 使用
你需要的是即时修改

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

您可以使用中间件存储当前用户:


然后,您可以使用
get\u current\u user()

获取用户。我们可以使用中间件类解决此问题。 在存储用户变量的位置创建singleton类

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
在signals中导入LoggedInUser类并获取当前用户

logged_in = LoggedInUser()
user = logged_in.user

如果您正在使用管理站点,为什么不使用自定义模型管理

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 )

每次保存对象时都会触发一个信号,不管它是由管理员还是某个与请求无关的进程执行的,也不是执行基于请求的操作的合适位置。由于不愿意处理线程的本地状态,我决定尝试另一种方法。据我所知,调用
save()
的线程中同步调用了
post\u save
pre\u 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
属性

注意:如
检查
模块文档中所述

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


不使用hack:在用户登录/注销时使用信号来记住谁登录,对于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
    # .........

这个想法是正确的,但争论的方向是错误的<代码>发送者(发送信号的类)总是第一位。更正,谢谢。。。您所说的是djanog标准,但是(就我使用的情况而言)在(实例,发件人)顺序中使用参数也可以(至少在我的代码中)…uname=instance.username要求在您的模型中有一个名为username?的字段?。。。。这不是我的情况…解决方案依赖于线程局部变量。出于各种原因,这些被认为是“坏的”。只是对@AaronC.deBruyn所说的一点评论——他发布的链接实际上与他的声明不一致,而公众舆论认为,使用本地线程来实现这一目的是可以接受的。2015年2月。这仍然是在Django信号中获取用户请求的唯一方法吗?这是正确答案,加上所需的预填充字段非常有用。这将适用于某些情况,但并非所有情况,例如对
m2m
关系的更改只能通过信号连接。先生,您是一个传奇。卓越的解决方案,正如广告中所宣传的那样有效。这种方法的优缺点?优缺点确实有效,实现起来更简单,并且避免了线程局部性(可能是一件坏事,也可能不是坏事)优缺点性能受到影响(必须针对每个信号扫描调用堆栈),无法通过测试工作-您需要添加额外的逻辑来从测试中提取请求对象。我已将其更改为反向(inspect.stack())因为在Django项目的62次迭代中,在迭代49中找到了get_响应,这告诉我们,在混响方向的扫描应该更有利可图。对62个项目进行反向反整+先扫描~10个项目的时间比先扫描~49个项目的时间要慢。用timeit做一些测试。但我很惊讶这两者之间的差别如此之小。只有当你的网站一次只有一个用户登录时,它才起作用。