布尔注释导致重复?
Boolean annotation resulting in duplicates?
我正在尝试实现一个基于外键 table 的基本 'favourites' 系统。
假设我有以下简单模型:
class Item(models.Model)
id = models.IntegerField()
class User(models.Model)
id = models.IntegerField()
class UserFavourites(models.Model)
user = models.ForeignKey(User, related_name='user_for_fav_rel')
item = models.ForeignKey(Item, related_name='item_for_fav_rel')
现在我为项目生成以下查询集,以查看它们是否已被用户标记为收藏夹:
queryset = Item.objects.all()
USER_ID = request.user.id
queryset = queryset.annotate(
favourite=Case(
When(
item_for_fav_rel__user__id=USER_ID,
then=Value('True')
),
default=Value('False'),
output_field=BooleanField()
)
)
所有这一切都很好,但在响应中,如果该项目确实被收藏,我会在查询集中收到该特定项目的副本。知道如何避免这种情况吗?
结果 SQL 查询(已编辑为我认为的最小示例...)
SELECT
"core_item"."id",
CASE
WHEN "core_userfavourites"."user_id" = 1 THEN True
ELSE False
END AS "favourite"
FROM "core_item"
LEFT OUTER JOIN "core_userfavourites"
ON ("core_item"."id" = "core_userfavourites"."item_id")
问题是 core_item 和 core_userfavorites 的每个组合都会得到一行。如果没有原始 SQL,似乎没有办法完全按照您的尝试进行操作,但幸运的是 Django 最近(1.11)添加了编写 SubQuery 子句的功能,您可以在此处使用
from django.db.models.expressions import OuterRef, Subquery
queryset = Item.objects.all()
USER_ID = request.user.id
user_favorites = UserFavourites.objects.filter(
user_id=USER_ID,
item_id=OuterRef('id')
)[:1].values('user_id')
queryset = queryset.annotate(user_favorite=Subquery(user_favorites))
如果用户已收藏,这将在 user_favorite
字段中为您提供 user_id
,如果未收藏,则为 None
。
基本上你正在编写一个子查询来从相关的 table.
中选择一个任意值
我正在尝试实现一个基于外键 table 的基本 'favourites' 系统。
假设我有以下简单模型:
class Item(models.Model)
id = models.IntegerField()
class User(models.Model)
id = models.IntegerField()
class UserFavourites(models.Model)
user = models.ForeignKey(User, related_name='user_for_fav_rel')
item = models.ForeignKey(Item, related_name='item_for_fav_rel')
现在我为项目生成以下查询集,以查看它们是否已被用户标记为收藏夹:
queryset = Item.objects.all()
USER_ID = request.user.id
queryset = queryset.annotate(
favourite=Case(
When(
item_for_fav_rel__user__id=USER_ID,
then=Value('True')
),
default=Value('False'),
output_field=BooleanField()
)
)
所有这一切都很好,但在响应中,如果该项目确实被收藏,我会在查询集中收到该特定项目的副本。知道如何避免这种情况吗?
结果 SQL 查询(已编辑为我认为的最小示例...)
SELECT
"core_item"."id",
CASE
WHEN "core_userfavourites"."user_id" = 1 THEN True
ELSE False
END AS "favourite"
FROM "core_item"
LEFT OUTER JOIN "core_userfavourites"
ON ("core_item"."id" = "core_userfavourites"."item_id")
问题是 core_item 和 core_userfavorites 的每个组合都会得到一行。如果没有原始 SQL,似乎没有办法完全按照您的尝试进行操作,但幸运的是 Django 最近(1.11)添加了编写 SubQuery 子句的功能,您可以在此处使用
from django.db.models.expressions import OuterRef, Subquery
queryset = Item.objects.all()
USER_ID = request.user.id
user_favorites = UserFavourites.objects.filter(
user_id=USER_ID,
item_id=OuterRef('id')
)[:1].values('user_id')
queryset = queryset.annotate(user_favorite=Subquery(user_favorites))
如果用户已收藏,这将在 user_favorite
字段中为您提供 user_id
,如果未收藏,则为 None
。
基本上你正在编写一个子查询来从相关的 table.
中选择一个任意值