Django:为什么注释将项目添加到我的查询集中?
Django: why does annotate add items to my queryset?
我正在努力做一些简单的事情。
我有 Item
objects,用户可以将它们标记为收藏夹。
由于这些项目不属于用户,所以我决定在 User
和 Item
之间使用 ManyToMany 来记录收藏关系。如果用户在 favoriters
项字段中,则表示用户收藏了它。
然后,当我为特定用户检索 objects 时,我想注释每个项目以指定它是否被用户收藏。我为此制作了 add_is_favorite_for()
方法。
这是(简化的)代码:
class ItemQuerySet(query.QuerySet):
def add_is_favorite_for(self, user):
"""add a boolean to know if the item is favorited by the given user"""
condition = Q(favoriters=user)
return self.annotate(is_favorite=ExpressionWrapper(condition, output_field=BooleanField()))
class Item(models.Model):
objects = Manager.from_queryset(ItemQuerySet)()
favoriters = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
这没有按预期工作,Django 似乎为每个 收藏该项目的用户添加了一个项目。它会导致疯狂的事情,例如:
Item.objects.count() # 10
Item.objects.add_is_favorite_for(some_user).count() # 16 -> how the hell an annotation can return more results than initial queryset?
我在这里遗漏了一些东西...
您可以更改注释中的条件以使用子查询,获取用户收藏的所有商品,然后测试商品的 ID 是否在子查询中。
这应该可以解决您的重复问题:
def add_is_favorite_for(self, user):
return self.annotate(is_favorite=ExpressionWrapper(
Q(id__in=Item.objects.filter(favoriters=user).values('id')),
output_field=BooleanField()
))
我正在努力做一些简单的事情。
我有 Item
objects,用户可以将它们标记为收藏夹。
由于这些项目不属于用户,所以我决定在 User
和 Item
之间使用 ManyToMany 来记录收藏关系。如果用户在 favoriters
项字段中,则表示用户收藏了它。
然后,当我为特定用户检索 objects 时,我想注释每个项目以指定它是否被用户收藏。我为此制作了 add_is_favorite_for()
方法。
这是(简化的)代码:
class ItemQuerySet(query.QuerySet):
def add_is_favorite_for(self, user):
"""add a boolean to know if the item is favorited by the given user"""
condition = Q(favoriters=user)
return self.annotate(is_favorite=ExpressionWrapper(condition, output_field=BooleanField()))
class Item(models.Model):
objects = Manager.from_queryset(ItemQuerySet)()
favoriters = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
这没有按预期工作,Django 似乎为每个 收藏该项目的用户添加了一个项目。它会导致疯狂的事情,例如:
Item.objects.count() # 10
Item.objects.add_is_favorite_for(some_user).count() # 16 -> how the hell an annotation can return more results than initial queryset?
我在这里遗漏了一些东西...
您可以更改注释中的条件以使用子查询,获取用户收藏的所有商品,然后测试商品的 ID 是否在子查询中。
这应该可以解决您的重复问题:
def add_is_favorite_for(self, user):
return self.annotate(is_favorite=ExpressionWrapper(
Q(id__in=Item.objects.filter(favoriters=user).values('id')),
output_field=BooleanField()
))