Получить текущий входной сигнал пользователя в Django

Я просто использую сайт admin в Django. У меня есть 2 сигнала Django (pre_save и post_save). Я хотел бы иметь имя пользователя текущего пользователя. Как мне это сделать? Кажется, я не могу отправить запрос, или я этого не понял.

Спасибо

Ответ 1

если вы используете сайт администратора, почему бы не использовать кукурузную модель admin

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

Не желая вмешиваться в нить-локальное состояние, я решил попробовать другой подход. Насколько я могу судить, обработчики сигналов 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.

Ответ 3

В обоих сигналах сигнал посылает три аргумента,

  • Отправитель
  • Instance
  • Использование

Вам нужно, чтобы Момент был изменен...

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

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

Ответ 4

Вы можете использовать промежуточное программное обеспечение для хранения текущего пользователя: http://djangosnippets.org/snippets/2179/

Затем вы сможете получить пользователя с get_current_user()

Ответ 5

Мы можем решить эту проблему, используя классы промежуточного программного обеспечения. Создайте одноэлементный класс, в котором будет храниться пользовательская переменная.

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, и вставьте промежуточное программное обеспечение после "django.contrib.auth.middleware.AuthenticationMiddleware" в settings.py

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