1

嘿,伙计们,我有一个看起来像这样的模型:

class Interaction(DateAwareModel, UserAwareModel):
  page = models.ForeignKey(Page)
  container = models.ForeignKey(Container, blank=True, null=True)
  content = models.ForeignKey(Content)
  interaction_node = models.ForeignKey(InteractionNode)
  kind = models.CharField(max_length=3, choices=INTERACTION_TYPES)

我希望能够执行一个查询来获取按容器分组的交互计数,然后按种类分组。这个想法是输出 JSON 数据结构(由活塞处理的序列化)看起来像这样:

"data": {
   "container 1": {
       "tag_count": 3, 
       "com_count": 1
   },
   "container 2": {
       "tag_count": 7, 
       "com_count": 12
   },
   ...
}

SQL 看起来像这样:

SELECT container_id, kind, count(*) FROM rb_interaction GROUP BY container_id, kind;

关于如何使用 ORM 按多个字段分组的任何想法?(如果我可以避免 id,我不想为这个项目编写原始查询)这似乎是一个简单而常见的查询。

在你问之前:我已经看过 django 聚合文档和原始查询文档。

更新 根据以下建议,我创建了一个自定义管理器来处理此问题:

class ContainerManager(models.Manager):
    def get_query_set(self, *args, **kwargs):
        qs = super(ContainerManager, self).get_query_set(*args, **kwargs)
        qs.filter(Q(interaction__kind='tag') | Q(interaction__kind='com')).distinct()
        annotations = {
            'tag_count':models.Count('interaction__kind'),
            'com_count':models.Count('interaction__kind')
        }
        return qs.annotate(**annotations)

这仅计算类型标签或 com 的交互,而不是通过 group by 检索标签和 com 的计数。很明显,它从代码中以这种方式工作,但想知道如何修复它......

4

1 回答 1

2

创建自定义管理器:

class ContainerManager(models.Manager):
    def get_query_set(self, *args, **kwargs):
        qs = super(ContainerManager, self).get_query_set(*args, **kwargs)
        annotations = {'tag_count':models.Count('tag'), 'com_count':models.Count('com')}
        return qs.annotate(**annotations)

class Container(models.Model):
    ...
    objects = ContainerManager()

然后,Container查询将始终包含tag_countcom_count属性。您可能需要修改注释,因为我没有您的模型副本可供参考;我只是猜测了字段名称。

更新:

因此,在更好地了解您的模型之后,注释将无法满足您的需求。真正了解有多少Containers 有kind'tag' 或 'com' 的唯一方法是:

tag_count = Container.objects.filter(kind='tag').count()
com_count = Container.objects.filter(kind='com').count()

注释不会为您提供该信息。我认为可以编写自己的聚合和注释,所以这可能是一个可能的解决方案。但是,我自己从来没有这样做过,所以我不能在那里给你任何指导。您可能会坚持使用直接 SQL。

于 2011-05-24T21:45:33.937 回答