I'm trying to query the users presents in a certain conversation. I finally got it working with this annotation:
products = products.annotate(
conversation_users=Subquery(
Conversation.objects.filter(
product=OuterRef('pk')
).annotate(
users_array=ArrayAgg('users__username')
).values_list('users_array', flat=True)[:1]
)
)
This is returning a list with the user present in the conversation (in most cases only two). I need to exclude from there the request.user so I get always the value of the user who I am having the conversation with.
I tried using this Q query trying to exclude the request.user:
.filter(~Q(users=user)).values_list('users_array', flat=True)[:1]
)
but it is making the field now return None. How can I accomplish that?
Edit 1:
Those are the relevant models, Product model:
class Product(models.Model):
creator = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='anken')
content = models.TextField(blank=True, null=True)
date = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
intouch = models.ManyToManyField(
User, related_name='product_intouch', blank=True)
And this is the Conversation model:
class Conversation(models.Model):
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name='conversations')
users = models.ManyToManyField(User, related_name='conversations')
def validate_unique(self, *args, **kwargs):
super().validate_unique(*args, **kwargs)
if Conversation.objects.filter(product=self.product, users__in=self.users.all()).exists():
raise ValidationError(
'A conversation with the same Product and user already exists.')
You filter this out in the aggregate:
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import OuterRef, Q, Subquery
products = products.annotate(
conversation_users=Subquery(
Conversation.objects.filter(
product=OuterRef('pk'),
)
.annotate(users_array=ArrayAgg('users__username', filter=~Q(users=user)))
.values_list('users_array', flat=True)[:1]
)
)