Django:过滤注释结果 [英] Django: Filtering Annotated Results

查看:157
本文介绍了Django:过滤注释结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个模型:

 类状态(models.Model):
title = models.CharField

类任务(models.Model):
user = models.ForeignKey(User)
status = models.ForeignKey(状态,默认= 1)
title = models.CharField(max_length = 128)

我想创建一个包含所有的状态我在我的状态模型,例如:今天,明天,等待,计划,垃圾



足够简单。然后,我想显示分配给每个状态的任务数,谢谢SO,也很简单:

  Status.objects.all ().annotate(Count('task'))

这很好地创建了我的所有状态和数量分配给每个的任务数量:


今天(1)
明天(1)
等待(0)
计划(2)
垃圾邮件(7)


现在如何过滤上述值,以便它们只反映当前登录的用户。向查询器添加过滤器似乎可以消除任何有用的零状态。我想要这些零状态。我目前的想法涉及 Q()

  Status.objects.filter (Q(task__user = 1)| Q(task__user__isnull = True))。注释(Count('task'))

这不行。



任何想法?



strong>

  Status.objects.all()。annotate(Count('task'))

发送:


收件箱(3)
今天(0)
下一页(1)
等待(0)
计划(1)
以后(0)
有一天(0)
档案(0)
垃圾邮件(0)


很棒,但其中1个这些收件箱任务和预定是为另一个用户。好的,所以让我们试试过滤。

  Status.objects.filter(task__user = current_user).annotate(Count('task') )




收件箱(2)
下一页(1) / p>

作品! Sorta ....我(正如我打电话给他们)零的状态不在那里。我应该说,任何没有与当前登录用户相关联的任务的状态都不会显示出来。我想要它出现。

解决方案

嗯,我认为你可以实现这一点的唯一方法是使用 LEFT OUTER JOIN s或 SUBQUERY s ...我不知道如何在django中表达左外连接,所以我'将使用 SUBQUERY 路径。以下将使用某些手工制作的SQL extra 享受!

 你应该有任务和状态导入
x = Status.objects.extra(select = {
task__count:SELECT COUNT(*)FROM%(task_table)s WHERE%(task_table)s。% task_status_id)s =%(status_table)s。%(status_pk)s AND%(task_table)s。%(user_col)s =%(user_id)d%
{
task_table _meta.db_table,
task_status_id:Task._meta.get_field_by_name(status)[0] .column,
status_table:Status._meta.db_table,
status_pk Status._meta.pk.column,
user_col:Task._meta.get_field_by_name(user)[0] .column,
user_id:1

}
})

请注意,我正在使用很多...未记录的功能(例如:Task._meta),这些可能会在未来崩溃(让我们不要)...但是他们做这个工作。


I have two models:

class Status(models.Model):
    title = models.CharField(max_length=32)

class Task(models.Model):
    user = models.ForeignKey(User)
    status = models.ForeignKey(Status, default=1)
    title = models.CharField(max_length=128)

I want to create a nav list that contains all of the statuses I have in my status model, example: Today, Tomorrow, Waiting, Scheduled, Trash

Simple enough. I then want to display the number of tasks assigned to each status, thanks to SO, also simple:

Status.objects.all().annotate(Count('task'))

This nicely creates a list of all of my statuses and a number the number of tasks assigned to each:

Today (1) Tomorrow (1) Waiting (0) Scheduled (2) Trash (7)

The trick with all of this is now how to filter the above values so that they only reflect the current logged in user. Adding a filter to the queryset seems to remove any zero statuses which makes sense. I want those zero statuses though. My current idea involves Q():

Status.objects.filter(Q(task__user=1) | Q(task__user__isnull=True)).annotate(Count('task'))

This does not work.

Any ideas?

Edit for Yuji

Status.objects.all().annotate(Count('task'))

Gives:

Inbox (3) Today (0) Next (1) Waiting (0) Scheduled (1) Later (0) Someday (0) Archives (0) Trash (0)

Great but 1 of those inbox tasks and scheduled are for another user. Ok, so let's try filtering.

Status.objects.filter(task__user=current_user).annotate(Count('task'))

Inbox (2) Next (1)

Works! Sorta.... My (as I called them) zero'ed out statuses aren't there. I should say, any status that doesn't have a task associated with it as that currently logged in user does not show up. I want it to show up.

解决方案

Well... the only way I think you can achieve this is with LEFT OUTER JOINs or SUBQUERYs... I have no idea on how to express left outer joins in django, so I'll go with the SUBQUERY path. The following will use extra with some handcrafted SQL, enjoy!

# you should have Task and Status imported
x = Status.objects.extra(select = {
    "task__count" : "SELECT COUNT(*) FROM %(task_table)s WHERE %(task_table)s.%(task_status_id)s = %(status_table)s.%(status_pk)s AND %(task_table)s.%(user_col)s = %(user_id)d" % 
    {
        "task_table" : Task._meta.db_table,
        "task_status_id" : Task._meta.get_field_by_name("status")[0].column,
        "status_table" : Status._meta.db_table,
        "status_pk" : Status._meta.pk.column,
        "user_col" : Task._meta.get_field_by_name("user")[0].column,
        "user_id" : 1

    }
})

Note that I'm using a lot of... undocumented features (for instance: Task._meta), these might break in the future (let's hope not)... but hey, they do the job.

这篇关于Django:过滤注释结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆