Как получить список аутентифицированных пользователей? - PullRequest
34 голосов
/ 27 апреля 2010

Я хотел бы отобразить список аутентифицированных пользователей.

По документации: http://docs.djangoproject.com/en/dev/topics/auth/

модели класса. Использование
is_authenticated () ¶
Всегда возвращает True. Это способ определить, был ли пользователь аутентифицирован. ...

Вы можете знать на стороне шаблона, является текущий Пользователь аутентифицирован или нет:

{% if user.is_authenticated%} {% endif%}

Но я не нашел способа получить список аутентифицированных пользователей.

Есть идеи?

Ответы [ 4 ]

66 голосов
/ 27 апреля 2010

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

(Это все не проверено, но, надеюсь, будет близко к работе).

Выбрать всех вошедших в систему пользователей ...

from django.contrib.auth.models import User
from django.contrib.sessions.models import Session
from django.utils import timezone

def get_all_logged_in_users():
    # Query all non-expired sessions
    # use timezone.now() instead of datetime.now() in latest versions of Django
    sessions = Session.objects.filter(expire_date__gte=timezone.now())
    uid_list = []

    # Build a list of user ids from that query
    for session in sessions:
        data = session.get_decoded()
        uid_list.append(data.get('_auth_user_id', None))

    # Query all logged in users based on id list
    return User.objects.filter(id__in=uid_list)

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

from django import template
from wherever import get_all_logged_in_users
register = template.Library()

@register.inclusion_tag('templatetags/logged_in_user_list.html')
def render_logged_in_user_list():
    return { 'users': get_all_logged_in_users() }

logged_in_user_list.html

{% if users %}
<ul class="user-list">
    {% for user in users %}
    <li>{{ user }}</li>
    {% endfor %}
</ul>
{% endif %}

Тогда на главной странице вы можете просто использовать его там, где вам нравится ...

{% load your_library_name %}
{% render_logged_in_user_list %}

EDIT

Для тех, кто говорит о 2-недельной постоянной проблеме, я предполагаю, что любой, желающий иметь листинг типа «активные пользователи», будет использовать настройку SESSION_EXPIRE_AT_BROWSER_CLOSE, хотя признать, что это не всегда так.

7 голосов
/ 04 марта 2014

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

models.py

class LoggedUser(models.Model):
    user = models.ForeignKey(User, primary_key=True)

    def __unicode__(self):
        return self.user.username

    def login_user(sender, request, user, **kwargs):
        LoggedUser(user=user).save()

    def logout_user(sender, request, user, **kwargs):
        try:
            u = LoggedUser.objects.get(user=user)
            u.delete()
        except LoggedUser.DoesNotExist:
            pass

    user_logged_in.connect(login_user)
    user_logged_out.connect(logout_user)

views.py

logged_users = LoggedUser.objects.all().order_by('username')
1 голос
/ 21 августа 2017

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

Где вы их получите;

  1. {{ request.online_now }} => отобразить весь список онлайн-пользователей.
  2. {{ request.online_now_ids }} => отобразить все идентификаторы пользователей онлайн.
  3. {{ request.online_now.count }} => показать всех пользователей онлайн.

Как настроить?

Создать файл middleware.py, где было сохранено местоположение settings.py, например:

projectname/projectname/__init__.py
projectname/projectname/middleware.py
projectname/projectname/settings.py

Затем следуйте этой строке;

from django.core.cache import cache
from django.conf import settings
from django.contrib.auth.models import User
from django.utils.deprecation import MiddlewareMixin

ONLINE_THRESHOLD = getattr(settings, 'ONLINE_THRESHOLD', 60 * 15)
ONLINE_MAX = getattr(settings, 'ONLINE_MAX', 50)


def get_online_now(self):
    return User.objects.filter(id__in=self.online_now_ids or [])


class OnlineNowMiddleware(MiddlewareMixin):
    """
    Maintains a list of users who have interacted with the website recently.
    Their user IDs are available as ``online_now_ids`` on the request object,
    and their corresponding users are available (lazily) as the
    ``online_now`` property on the request object.
    """

    def process_request(self, request):
        # First get the index
        uids = cache.get('online-now', [])

        # Perform the multiget on the individual online uid keys
        online_keys = ['online-%s' % (u,) for u in uids]
        fresh = cache.get_many(online_keys).keys()
        online_now_ids = [int(k.replace('online-', '')) for k in fresh]

        # If the user is authenticated, add their id to the list
        if request.user.is_authenticated():
            uid = request.user.id
            # If their uid is already in the list, we want to bump it
            # to the top, so we remove the earlier entry.
            if uid in online_now_ids:
                online_now_ids.remove(uid)
            online_now_ids.append(uid)
            if len(online_now_ids) > ONLINE_MAX:
                del online_now_ids[0]

        # Attach our modifications to the request object
        request.__class__.online_now_ids = online_now_ids
        request.__class__.online_now = property(get_online_now)

        # Set the new cache
        cache.set('online-%s' % (request.user.pk,), True, ONLINE_THRESHOLD)
        cache.set('online-now', online_now_ids, ONLINE_THRESHOLD)

Наконец, обновите ваш MIDDLEWARE внутренний файл projectname/projectname/settings.py:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
    ....
    # Custom middleware
    'projectname.middleware.OnlineNowMiddleware',
]

Для других условий вы также можете проверить, находится ли текущий пользователь в сети или нет:

{% if request.user in request.online_now %}
    {# do stuff #}
{% endif %}
1 голос
/ 27 апреля 2010

Нет простого встроенного способа сделать то, что вы хотите, о чем я знаю. Я бы попробовал комбинацию истекающих сеансов и фильтрации на last_login. Может быть, даже написать собственный менеджер для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...