Mixo
Mixo

Reputation: 191

queryset tag on template

I would show the users list, I return it by:

    active_sessions = Session.objects.filter(expire_date__gte=timezone.now())
    user_id_list = []
    user_name_list = []
    tot_active_sessions = active_sessions.count()
    for session in active_sessions:
        data = session.get_decoded()
        user_id_list.append(data.get('_auth_user_id', None))
    for k in user_id_list:
        user_name_list.append(User.objects.filter(id__in=k))
    if tot_active_sessions > _sessions_limit :
        logout(request)
        return  render(request, 'page/users.html',  context={'user_name_list': user_name_list})

in my template 'page/users.html':

{% for username in user_name_list %}
      {{ username }}
{% endfor %}

with the following result:

•<QuerySet [<User: guest2>]>
•<QuerySet [<User: guest1>]>

How can I obtain only:

•guest2
•guest1

In others situations I didn't see the queryset tag on my template, I haven't idea about this result..

Upvotes: 1

Views: 563

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476544

The view itself produces a list of QuerySets, not a list of Users, this is due to the:

for k in user_id_list:
    user_name_list.append(User.objects.filter(id__in=k))

You here thus include a filtered QuerySet, not a User object itself.

Nevertheless, your code in the view is rather complicated, and can be improved both in readability, and efficiency:

active_sessions = Session.objects.filter(expire_date__gte=timezone.now())
user_list = User.objects.filter(
    id__in=[session.get_decoded().get('_auth_user_id', None) for session in active_sessions]
)
tot_active_sessions = active_sessions.count()
if tot_active_sessions > _sessions_limit:
    logout(request)
    return  render(request, 'page/users.html',  context={'user_name_list': user_list })

Here we thus construct a single QuerySet that contains all the users with active sessions, and we render that list, we do not make a list of QuerySets. This will thus enumerate over users, you can also obtain the username values directly, with:

active_sessions = Session.objects.filter(expire_date__gte=timezone.now())
user_list = User.objects.filter(
    id__in=[session.get_decoded().get('_auth_user_id', None) for session in active_sessions]
).values_list('username', flat=True)
tot_active_sessions = active_sessions.count()
if tot_active_sessions > _sessions_limit:
    logout(request)
    return  render(request, 'page/users.html',  context={'user_name_list': user_list })

EDIT: In case we want to list users multiple times, if a user has multiple open sessions, we can still do this with a single database query, and then "unfold" the results in a list, like:

active_sessions = Session.objects.filter(expire_date__gte=timezone.now())
uids=[session.get_decoded().get('_auth_user_id', None) for session in active_sessions]
tot_active_sessions = active_sessions.count()
if tot_active_sessions > _sessions_limit:
    user_dict = dict(
        User.objects.filter(
        id__in=uids
    ).values_list('id', 'username'))
    user_list = [user_dict.get(_id) for _id in uids]
    logout(request)
    return  render(request, 'page/users.html',  context={'user_name_list': user_list })

Upvotes: 2

Related Questions