Reputation: 3615
This is my User object,
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, max_length=255)
mobile = PhoneNumberField(null=True)
username = models.CharField(null=False, unique=True, max_length=255)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
And this is my Quiz object,
class Quiz(Base):
category = models.ForeignKey(Category, related_name='quizzes', on_delete=models.CASCADE)
players = models.ManyToManyField(User)
This is the filter that I'm using to find quizzes of a particular category that the user has not played,
quiz = Quiz.objects.filter(category=category).exclude(players=user).order_by('created')[:1]
But the exclude is a list and thus doesn't work. How do I correctly frame this query to exclude the current user?
Upvotes: 1
Views: 615
Reputation: 477180
This answer aims to answer the following problem (since it is rather complicated, I want to make sure that it matches exactly):
"A queryset that contains
Quiz
zes where we exclude theQuiz
zes hat have exactly one participant in the list ofusers
". So those quizzes are not part of the queryset.
I would each time count the number of overlaps, and then exclude the Quiz
zes where the number of overlap is equal to zero. Something like:
Quiz.objects.filter(
Q(players__in=users) | Q(players__isnull=True)
).annotate(
overlap_size=Count('players')
).exclude(overlap_size=1)
We thus always calculate the "overlap": the number of users that are both in your list of users
, and in the list of the participants. Then we this exclude the Quiz
zes where that overlap is exactly one, hence quizes where there was exactly one participant that was in the users
list.
In case you want quizzes where the overlap is exactly one, you only have to replace the .exclude(..)
(at the end) with a .filter(..)
instead.
Upvotes: 1