【问题标题】:How to get the list of the authenticated users?如何获取经过身份验证的用户列表?
【发布时间】:2011-02-12 23:06:13
【问题描述】:

我想显示经过身份验证的用户列表。

关于文档:http://docs.djangoproject.com/en/dev/topics/auth/

类models.User
is_authenticated()¶
始终返回 True。这是一种判断用户是否已通过身份验证的方法。 ...

您可以在模板端知道当前用户是否已通过身份验证:

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

但是我没有找到获取认证用户列表的方法。

有什么想法吗?

【问题讨论】:

    标签: django authentication


    【解决方案1】:

    最可靠的解决方案是您在用户登录或注销时存储的内容。我看到了这个解决方案,我认为它值得分享。

    models.py

    ​​>
    from django.contrib.auth.signals import user_logged_in, user_logged_out
    
    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')
    

    【讨论】:

    • 我复制粘贴了您的代码,它工作得非常好,甚至比接受的答案更好,因为在某些情况下它没有检测到用户注销时(但我已经修改了 User 类)。关于您的解决方案,为了获得我必须做的真实登录用户:logged_users=[user.user for user in LoggedUser.objects.all()]
    • NameError: name 'user_logged_in' is not defined
    • 它是一个 django 信号,我已经更新了答案以包含导入。谢谢。
    【解决方案2】:

    听起来与此解决方案类似,您可以创建一个自定义中间件来执行此操作。我在这里找到了很棒的OnlineNowMiddleware。

    你会在哪里得到这些;

    1. {{ request.online_now }} => 显示所有在线用户列表。
    2. {{ request.online_now_ids }} => 显示所有在线用户 ID。
    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 %}
    

    【讨论】:

    • 知道如何修改它,以便在用户注销时从 online_now 中删除?
    • @PaddyPopeye 默认使用ONLINE_THRESHOLD 处理。因此,在用户退出 60 * 15 => 15 分钟后,自动从 online_now 中删除。
    • 感谢答案。但代码的问题在于,即使 ONLINE_THRESHOLD 处理了这个问题,它也不会反映在页面上。只有在手动刷新页面后,您才会看到用户已注销.. 任何建议
    • @PaddyPopeye 如果您需要实时方法,也许您可​​以使用 setInterval 中的 ajax post 处理它。例如:pastebin.com/3xVFpJiB
    • @是的,同时你可以根据需要删除它。
    【解决方案3】:

    根据 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 %}
    

    编辑

    对于那些谈论 2 周持续性问题的人,我假设任何想要拥有“活跃用户”类型列表的人都会使用 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置,但我知道这并不总是案例。

    【讨论】:

    • 非常感谢,这正是我想要的。杰拉德
    • 嗯,只是让您知道“未过期会话”将为您提供所有已登录 两周的人...如果您愿意,请查看 django-tracking当前活跃用户。
    • 与@jonwd7 相同的评论。检查 last_login 或更复杂的过滤可能会更好。 2 周几乎不能算作“当前”
    • 您可能会拼凑一些中间件,这些中间件会设置一个会话变量来为所有用户的最新请求添加时间戳,然后过滤那些不到 5 分钟的请求。那么上面的解决方案就可以很好地工作了。
    • 我使用get_all_logged_in_users 来获取活跃用户,但它在几天前停止工作?使用Python(2.7) 和Django(1.11)。
    【解决方案4】:

    据我所知,没有简单的内置方法可以做你想做的事。我会尝试结合使用过期会话和过滤 last_login。甚至可能为此编写一个自定义管理器。

    【讨论】:

    • 这是怎么做到的????
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    • 2021-04-07
    相关资源
    最近更新 更多