Django 查询 - 在带注释的计数过滤器中获取父对象
Django query - get parent object in annotated count filter
我有 3 个模型:
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(db_index=True, max_length=20, unique = True)
class Content(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True) #User.content_set.all() returns all Content objects of the content
contentURL = models.CharField(max_length=256, null=True)
thumbnailURL = models.CharField(max_length=256, null=True, blank=True)
second_content = models.OneToOneField('self', on_delete=models.SET_NULL, null=True, blank=True) #if this is not NULL, then the content has been uploaded with a second one and they form a pair to be retrieved together
timestamp = models.DateTimeField(auto_now_add=True)
class Fight(models.Model):
win_content = models.ForeignKey(Content, db_index=True, on_delete=models.SET_NULL, related_name="wins", null=True) #Content.wins.all() returns all Fight objects of the content in which this content has won
loss_content = models.ForeignKey(Content, db_index=True, on_delete=models.SET_NULL, related_name="losses", null=True) #Content.losses.all() returns all Fight objects of the content in which this content has lost
user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
is_private = models.BooleanField(db_index=True, default=False) #we will filter those out for user quality calculations
timestamp = models.DateTimeField(auto_now_add=True)
我正在尝试获取:
所有 Content
其中 second_content
不为空
用相关的 Fight
计数来注释每个内容:一次是赢,一次是输。
这是我的查询集:
contents = user.content_set.exclude(content__second_content=None).annotate(
win_count=Count('wins', filter=Q(wins__loss_content=second_content)),
loss_count=Count('losses', filter=Q(losses__win_content=second_content))
).order_by('-timestamp')
问题出在 Q(wins__loss_content=second_content)
。 second_content
未定义,因为它指的是 Fight
对象,而不是父对象。 如何引用父对象?我已经试过了Q(wins__loss_content=content__second_content)
也不行!
你可以使用F
object [Django-doc]来引用一个字段,例如F('content')
因此引用外键字段。
因此您可以在如下表达式中使用它:
contents = user.content_set.exclude(content__second_content=None).annotate(
win_count=Count('wins', filter=Q(wins__loss_content=<b>F('content')</b>)),
loss_count=Count('losses', filter=Q(losses__win_content=<b>F('content')</b>))
).order_by('-timestamp')
请注意,这里您计算了两个单独的 JOIN
,因此也许您应该添加 set a distinct=True
parameter [Django-doc] in your Count(..)
expression [Django-doc] 以避免计算相同的 wins
和 losses
两次。
我有 3 个模型:
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(db_index=True, max_length=20, unique = True)
class Content(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True) #User.content_set.all() returns all Content objects of the content
contentURL = models.CharField(max_length=256, null=True)
thumbnailURL = models.CharField(max_length=256, null=True, blank=True)
second_content = models.OneToOneField('self', on_delete=models.SET_NULL, null=True, blank=True) #if this is not NULL, then the content has been uploaded with a second one and they form a pair to be retrieved together
timestamp = models.DateTimeField(auto_now_add=True)
class Fight(models.Model):
win_content = models.ForeignKey(Content, db_index=True, on_delete=models.SET_NULL, related_name="wins", null=True) #Content.wins.all() returns all Fight objects of the content in which this content has won
loss_content = models.ForeignKey(Content, db_index=True, on_delete=models.SET_NULL, related_name="losses", null=True) #Content.losses.all() returns all Fight objects of the content in which this content has lost
user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
is_private = models.BooleanField(db_index=True, default=False) #we will filter those out for user quality calculations
timestamp = models.DateTimeField(auto_now_add=True)
我正在尝试获取:
所有
Content
其中second_content
不为空用相关的
Fight
计数来注释每个内容:一次是赢,一次是输。
这是我的查询集:
contents = user.content_set.exclude(content__second_content=None).annotate(
win_count=Count('wins', filter=Q(wins__loss_content=second_content)),
loss_count=Count('losses', filter=Q(losses__win_content=second_content))
).order_by('-timestamp')
问题出在 Q(wins__loss_content=second_content)
。 second_content
未定义,因为它指的是 Fight
对象,而不是父对象。 如何引用父对象?我已经试过了Q(wins__loss_content=content__second_content)
也不行!
你可以使用F
object [Django-doc]来引用一个字段,例如F('content')
因此引用外键字段。
因此您可以在如下表达式中使用它:
contents = user.content_set.exclude(content__second_content=None).annotate(
win_count=Count('wins', filter=Q(wins__loss_content=<b>F('content')</b>)),
loss_count=Count('losses', filter=Q(losses__win_content=<b>F('content')</b>))
).order_by('-timestamp')
请注意,这里您计算了两个单独的 JOIN
,因此也许您应该添加 set a distinct=True
parameter [Django-doc] in your Count(..)
expression [Django-doc] 以避免计算相同的 wins
和 losses
两次。