我只是在 Django 中使用管理站点。我有 2 个 Django 信号(pre_save 和 post_save)。我想拥有当前用户的用户名。我该怎么做?看来我不能发送请求或者我不明白。
谢谢
我只是在 Django 中使用管理站点。我有 2 个 Django 信号(pre_save 和 post_save)。我想拥有当前用户的用户名。我该怎么做?看来我不能发送请求或者我不明白。
谢谢
由于不愿意搞乱线程本地状态,我决定尝试一种不同的方法。据我所知,post_save和pre_save信号处理程序在调用save(). 如果我们处于正常的请求处理循环中,那么我们可以向上遍历堆栈以在某处找到请求对象作为局部变量。例如
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 实现中都存在。
如果您使用的是管理站点,为什么不使用自定义模型管理员
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 )
信号是每次保存对象时都会触发的东西,无论它是由管理员完成还是由与请求无关的某个进程完成,也不是真正适合执行基于请求的操作的地方
您可以使用中间件来存储当前用户:http ://djangosnippets.org/snippets/2179/
然后你就可以让用户get_current_user()
我们可以使用中间件类来解决这个问题。在将存储用户变量的位置创建单例类。
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
没有 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
# .........
在这两个信号中,信号发送三个参数,
您需要的是正在修改的即时...
def signal_catcher(sender, instance, **kwargs):
uname = instance.username