Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django查询(聚合和计数)_Django_Django Models_Django Orm_Django Piston - Fatal编程技术网

Django查询(聚合和计数)

Django查询(聚合和计数),django,django-models,django-orm,django-piston,Django,Django Models,Django Orm,Django Piston,嘿,伙计们,我有一个这样的模型: class Interaction(DateAwareModel, UserAwareModel): page = models.ForeignKey(Page) container = models.ForeignKey(Container, blank=True, null=True) content = models.ForeignKey(Content) interaction_node = models.ForeignKey(Inter

嘿,伙计们,我有一个这样的模型:

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)
"data": {
   "container 1": {
       "tag_count": 3, 
       "com_count": 1
   },
   "container 2": {
       "tag_count": 7, 
       "com_count": 12
   },
   ...
}
SELECT container_id, kind, count(*) FROM rb_interaction GROUP BY container_id, kind;
我希望能够执行一个查询,以获得按容器分组的交互数量,然后再按种类分组。其想法是输出JSON数据结构(由活塞负责序列化)如下所示:

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)
"data": {
   "container 1": {
       "tag_count": 3, 
       "com_count": 1
   },
   "container 2": {
       "tag_count": 7, 
       "com_count": 12
   },
   ...
}
SELECT container_id, kind, count(*) FROM rb_interaction GROUP BY container_id, kind;
SQL将如下所示:

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)
"data": {
   "container 1": {
       "tag_count": 3, 
       "com_count": 1
   },
   "container 2": {
       "tag_count": 7, 
       "com_count": 12
   },
   ...
}
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的计数。很明显,从代码中可以看出它是这样工作的,但不知道如何修复它…

创建一个自定义管理器:

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\u count
com\u count
属性。您可能需要修改注释,因为我没有模型的副本可供参考;我只是猜到了字段名

更新:

因此,在对模型有了更好的理解之后,注释将无法满足您的需求。实际上,要获得“tag”或“com”的
容器的
种类的计数,唯一的方法是:

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

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

响应非常好,但我主要关心的是:我希望能够在数据库中完成聚合工作,而不是迭代容器。我可能错了,但这似乎会计算每个容器的标记和注释(隐含循环),而使用GROUPBY子句会更好地使用DB引擎。思想?没有迭代<代码>注释
过滤器
和queryset API的其余部分类似。它只是将内容附加到最终将发送到DB的SQL中。只有一个查询。Kind实际上在我的交互模型上,如果我想在“interaction\uuuu Kind”=“tag”或“com”中注释count,您介意提到您将如何做吗?只需在
之前插入
.filter(Q(interaction\uu Kind='tag')| Q(interaction\uu Kind='com')).distinct()
Q
位于
django.db.models
中。是的,根据您的更新,它不起作用。我写这个答案是基于这样一个假设,即
tag
com
是“可数的”,即外键。我将更新上面的答案,但您可能不会喜欢;)。