Django: сигнал при входе пользователя в систему?



в моем приложении Django мне нужно запустить несколько периодических фоновых заданий, когда пользователь входит в систему и перестает запускать их, когда пользователь выходит из системы, поэтому я ищу элегантный способ




  1. получить уведомление о входе/выходе пользователя

  2. запрос статуса входа пользователя


С моей точки зрения, идеальным решением будет




  1. сигнал, посланный каждым django.contrib.auth.views.login и ... views.logout

  2. метод django.contrib.auth.models.User.is_logged_in(), аналогично ... User.is_active() или ... User.is_authenticated()


Django 1.1.1 не имеет этого, и я не хочу исправлять источник и добавлять его (не уверен, как это сделать, в любом случае).



в качестве временного решения я добавил is_logged_in логическое поле для модели UserProfile, которое очищается по умолчанию, устанавливается при первом попадании пользователя на целевую страницу (определяется LOGIN_REDIRECT_URL = '/') и запрашивается в последующих запросах. Я добавил его в UserProfile, поэтому мне не нужно наследовать и настраивать встроенный Модель пользователя только для этой цели.



мне не нравится это решение. Если пользователь явно нажимает кнопку выхода из системы, я могу очистить флаг, но большую часть времени пользователи просто покидают страницу или закрывают браузер; очистка флага в этих случаях не кажется мне прямой. Кроме того (это скорее ясность модели данных, хотя),is_logged_in принадлежит не в UserProfile, а в пользовательской модели.



может ли кто-нибудь придумать альтернативные подходы ?

762   8  

8 ответов:

вы можете использовать такой сигнал (я вставил свой models.py)

from django.contrib.auth.signals import user_logged_in


def do_stuff(sender, user, request, **kwargs):
    whatever...

user_logged_in.connect(do_stuff)

см. django docs: https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals и вот http://docs.djangoproject.com/en/dev/topics/signals/

один из вариантов может заключаться в том, чтобы обернуть представления входа/выхода Django своими собственными. Например:

from django.contrib.auth.views import login, logout

def my_login(request, *args, **kwargs):
    response = login(request, *args, **kwargs)
    #fire a signal, or equivalent
    return response

def my_logout(request, *args, **kwargs):
    #fire a signal, or equivalent
    return logout(request, *args, **kwargs)

затем вы используете эти представления в своем коде, а не в Django, и вуаля.

что касается запроса статуса входа, это довольно просто, если у вас есть доступ к объекту запроса; просто проверьте атрибут пользователя запроса, чтобы узнать, является ли он зарегистрированным пользователем или анонимным пользователем, и бинго. Чтобы процитировать Джанго документация:

if request.user.is_authenticated():
    # Do something for logged-in users.
else:
    # Do something for anonymous users.

если у вас нет доступа к объекту запроса, то определить, вошел ли текущий пользователь в систему, будет сложно.

Edit:

к сожалению, вы не сможете получить User.is_logged_in() функциональность - это ограничение протокола HTTP. Однако если вы сделаете несколько предположений, вы сможете приблизиться к тому, что хотите.

во-первых, почему вы не можете получить эту функциональность? Ну, вы не можете сказать разницу между тем, кто закрывает браузер, или кто-то проводит некоторое время на странице, прежде чем выбрать новый. Нет никакого способа, чтобы сказать через HTTP, когда кто-то уходит с сайта или закрывает браузер.

таким образом, у вас есть два варианта здесь, которые не являются совершенными:

  1. используйте Javascript unload событие, чтобы поймать, когда пользователь покидает страницу. Вам нужно будет написать некоторую осторожную логику, чтобы убедиться, что вы не выходите из пользователя, когда они все еще навигация код однако сайта.
  2. пожарная выход сигнал всякий раз, когда пользователь входит в систему, просто чтобы быть уверенным. Кроме того, создайте задание хрона, которое выполняется довольно часто, чтобы очистить истекшие сеансы-когда истекший сеанс удаляется, проверьте, что пользователь сеанса (если он не является анонимным) не имеет более активных сеансов, и в этом случае вы запускаете сигнал выхода.

эти решения грязные и не идеальные, но они лучшее, что вы можете сделать, к сожалению.

в дополнение к @PhoebeB ответ: вы также можете использовать @receiver декоратор такой:

from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver

@receiver(user_logged_in)
def post_login(sender, user, request, **kwargs):
    ...do your stuff..`

и если вы положите его в signals.py в вашем приложении dir, а затем добавьте это в app.py:

def ready(self):
    import app_name.signals`

единственный надежный способ (который также определяет, когда пользователь закрыл браузер) - это обновить некоторые

вывод выхода из системы, в отличие от того, чтобы они явно нажимали кнопку (что никто не делает), означает выбор количества времени простоя, которое приравнивается к "выходу из системы". phpMyAdmin использует по умолчанию 15 минут, некоторые банковские сайты используют всего лишь 5 минут.

самый простой способ реализации этого - изменить время существования файлов cookie. Вы можете сделать это для всего сайта, указав settings.SESSION_COOKIE_AGE. Кроме того, вы можете изменить его для каждого пользователя (на основе некоторых произвольный набор критериев), с помощью HttpResponse.setcookie(). Вы можете централизовать этот код, создав свою собственную версию render_to_response() и имея его установить время жизни на каждый ответ.

грубая идея-вы можете использовать промежуточное программное обеспечение для этого. Это промежуточное программное обеспечение может обрабатывать запросы и пожарный сигнал, когда запрашивается соответствующий URL. Он также может обрабатывать ответы и сигнал огня, когда данное действие фактически успешно.

быстрое решение для этого было бы, в _ _ init _ _. py вашего приложения поместите следующий код:

from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver


@receiver(user_logged_in)
def on_login(sender, user, request, **kwargs):
    print('User just logged in....')

вы можете использовать такой:

from django.contrib.auth.signals import user_logged_out, user_logged_in

@login_required
def user_logout(request):
    logout(request)
    user_logged_out()
    return redirect('post_list')

Comments

    Ничего не найдено.