Django可以嵌套查询和排除

T. *_*one 1 django django-orm django-queryset

我需要一些帮助将这个查询放在Django中.我简化了这里的例子,只是简单地切入了这一点.

MyModel(models.Model):
    created = models.DateTimeField()
    user = models.ForeignKey(User)
    data = models.BooleanField()
Run Code Online (Sandbox Code Playgroud)

我想用英语创建的查询听起来像:

给我昨天创建的数据为False的每条记录,在同一范围内,对于给定用户,数据永远不会显示为True

这是一个示例输入/输出,如果不清楚的话.

表值

ID   Created    User    Data

1    1/1/2010   admin   False
2    1/1/2010   joe     True
3    1/1/2010   admin   False
4    1/1/2010   joe     False
5    1/2/2010   joe     False
Run Code Online (Sandbox Code Playgroud)

输出查询集

1    1/1/2010   admin   False
3    1/1/2010   admin   False
Run Code Online (Sandbox Code Playgroud)

我要做的是排除#4记录.这是因为在给定范围"昨天"中,对于记录#2中的用户,数据显示为True一次,因此将排除记录#4.

从某种意义上说,似乎有2个查询正在进行中.一个用于确定给定范围内的记录,另一个用于排除与"True"记录相交的记录.

如何使用Django ORM进行此查询?

Oli*_*Oli 5

您不需要嵌套查询.您可以生成坏用户PK的列表,然后在下一个查询中排除包含这些PK的记录.

bad = list(set(MyModel.obejcts.filter(data=True).values_list('user', flat=True)))
# list(set(list_object)) will remove duplicates
# not needed but might save the DB some work

rs = MyModel.objects.filter(datequery).exclude(user__pk__in=bad)
# might not need the pk in user__pk__in - try it
Run Code Online (Sandbox Code Playgroud)

你可以把它浓缩成一行,但我认为这就像你得到的一样整洁.2个查询并不是那么糟糕.

编辑:您可能想阅读以下文档:

http://docs.djangoproject.com/en/dev/ref/models/querysets/#in

这听起来像是自动嵌套查询(因此只有一个查询在数据库中触发),如果它是这样的:

bad = MyModel.objects.filter(data=True).values('pk')
rs  = MyModel.objects.filter(datequery).exclude(user__pk__in=bad)
Run Code Online (Sandbox Code Playgroud)

MySQL没有很好地优化这一点,所以我上面的代码(2个完整查询)实际上可以更快地运行.

试试两个并参加比赛吧!