英文:
Exclude user from an annotation query
问题
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.
这返回一个包含在对话中的用户列表(在大多数情况下只有两个)。我需要从中排除request.user
,以便始终获取我正在进行对话的用户的值。
I tried using this Q query trying to exclude the request.user:
我尝试使用以下的 Q 查询来排除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?
但它导致该字段现在返回 None。我该如何实现这一点?
Edit 1:
Those are the relevant models, Product model:
以下是相关的模型,Product 模型:
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:
这是 Conversation 模型:
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.')
Is there anything else you need assistance with?
英文:
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.')
答案1
得分: 1
你可以在聚合函数中过滤掉这部分内容:
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]
)
)
英文:
You filter this out in the aggregate:
<pre><code>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', <b>filter=~Q(users=user)</b>))
.values_list('users_array', flat=True)[:1]
)
)</code></pre>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论