Django模型管理器在做聚合查询时与相关对象不兼容

1 投票
1 回答
526 浏览
提问于 2025-04-15 21:35

我在处理一个多对多关系的字段时,遇到了聚合查询的问题。

这是我的模型:

class SortedTagManager(models.Manager):
    use_for_related_fields = True

    def get_query_set(self):
        orig_query_set = super(SortedTagManager, self).get_query_set()
        # FIXME `used` is wrongly counted
        return orig_query_set.distinct().annotate(
                    used=models.Count('users')).order_by('-used')


class Tag(models.Model):
    content = models.CharField(max_length=32, unique=True)
    creator = models.ForeignKey(User, related_name='tags_i_created')
    users = models.ManyToManyField(User, through='TaggedNote',
                                   related_name='tags_i_used')

    objects_sorted_by_used = SortedTagManager()

class TaggedNote(models.Model):
    """Association table of both (Tag , Note) and (Tag, User)"""
    note = models.ForeignKey(Note) # Note is what's tagged in my app
    tag = models.ForeignKey(Tag)
    tagged_by = models.ForeignKey(User)

    class Meta:
        unique_together = (('note', 'tag'),)

不过,当我直接查询这个模型时,聚合字段used的值才是正确的:

for t in Tag.objects.all(): print t.used # this works correctly

for t in user.tags_i_used.all(): print t.used #prints n^2 when it should give n

你能告诉我哪里出错了吗?谢谢!

1 个回答

2

我现在已经搞清楚问题出在哪里,以及怎么解决了 :)

  1. 正如Django文档中所说:

Django会把一个类中定义的第一个管理器视为“默认”管理器,Django的多个部分会专门使用这个管理器来处理该模型。

在我的情况下,我需要确保SortedTagManager是第一个定义的Manager

2.我应该统计notes而不是users

Count('notes', distinct=True)

撰写回答