0

I have a Django model defined as follows:

class Session(models.Model):
    ...
    leader = models.ForeignKey(User, related_name='leader')
    follower = models.ForeignKey(User, related_name='follower')
    ...

Now let's say I have a QuerySet of Session objects:

some_sessions = Session.objects.filter(some_criteria=True)

How can I get a simple count of unique Users that have been either a leader or follower in any Session in some_sessions?

For example, a particular User may have been a leader in some number of Session objects, but a follower in a handful of other Session objects. That particular User should only contribute 1 to the desired unique Users count.

There are of course some naive solutions to this, but for performance reasons, I'm wondering if there's a solution that leverages the power of QuerySets a bit more, if possible.

EDIT: To clarify, here's a naive method that gives the result I need:

active_user_ids = set()
some_sessions = Session.objects.filter(some_criteria=True)
for session in some_sessions:
    active_user_ids.add(session.leader.id)
    active_user_ids.add(session.follower.id)
all_active_users = User.objects.filter(id__in=active_user_ids).count()
2
  • Try: User.leader_set.all().count() and User.follower_set.all().count() Commented Nov 19, 2019 at 6:22
  • @user6837382 thank you, but this would not get me the count that I want. For example, if users 1-100 are leaders and users 51-150 are followers, your method would result in a total count of 200, not the desired 150. Commented Nov 19, 2019 at 6:25

2 Answers 2

1

A smart way of doing this is querying User instead of Session. Read more here.

from django.db.models import Q
# ... Other import here

users = User.objects.all(Q(leader__isnull=False) | Q(follower__isnull=False),).distinct()

This will give you any user where either related relations leader/follower is null.

If you want to add some filters based on sessions values, you could do something like:

sessions = Session.objects.filter(**your_filters)
users = User.objects.all(
    Q(leader__in=sessions) | Q(follower__in=sessions),).distinct()
Sign up to request clarification or add additional context in comments.

4 Comments

The problem here is that leader and follower are fields of Session, not User.
Using related_name will make your relations available within user instances docs.djangoproject.com/en/2.2/ref/models/fields/…
Thank you! Finally, let's say that it's not all_sessions = Session.objects.all(), but instead some_sessions = Session.objects.filter(some_criteria=True). (I plan to vary the Session queryset.) How can I get a count of unique Users that have been either a leader or follower in some_sessions?
Just added an example in response
0

For get a simple count of unique User use count method.

active_user_ids = set()
all_sessions = Session.objects.all()
for session in all_sessions:
    active_user_ids.add(session.leader.id)
    active_user_ids.add(session.follower.id)
all_active_users = User.objects.filter(id__in=active_user_ids).count()

1 Comment

Thanks for seeing the typo. It so happens that I already did have that in my code; I just copy/pasted incorrectly. I have updated my question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.