Gevorg Hakobyan
Gevorg Hakobyan

Reputation: 327

Django: check on model with manytomany field if object is in that list with filter

Let's say we have a Notification model with manytomany=ManyToManyField(User, blank=True) field with User model. How to annotate a field is_in_manytomany to return boolean with True and False only depending on a condition, whether self.request.user is in Notification ManyToMany field or not. This code below returns weird True and False and also None, regardless of the default value of BooleanField.

user = User.objects.get(id=1)

qs = Notification.objects.all().annotate(
                is_in_manytomany =ExpressionWrapper(
                    Q(manytomany__in = [user]),
                    output_field=BooleanField(default=True)
                )
            )

for item in qs:
    print(item.is_in_manytomany)

What am I doing wrong? How do you get a True/False annotation on the given condition?

Upvotes: 1

Views: 627

Answers (1)

Gevorg Hakobyan
Gevorg Hakobyan

Reputation: 327

Okay, I hope this helps someone else: We need to put Q | Q in Q to achieve the results

user = User.objects.get(id=1)

qs = Notification.objects.all().annotate(
                is_in_manytomany=ExpressionWrapper(
                    Q(Q(manytomany=user)| Q(manytomany=None)),
                    output_field=BooleanField()
                )
            )

for item in qs:
    print(item.is_in_manytomany)

Explanation: we did not need to do manytomany__in=[user], because its a ManyToMany field; manytomany=user is enough, since some objects have manytomany=None (because in my case the manytomany=ManyToManyField(User, blank=True), we need to add the second Q(manytomany=None). Also to reverse the boolean we can add ~ to any Q expression.

Upvotes: 1

Related Questions