Python 返回跨多个表的结果的最有效的Django查询

Python 返回跨多个表的结果的最有效的Django查询,python,django,Python,Django,我正试图以最有效的方式在Django中执行一个相当复杂的查询,但我不知道如何开始。我有这些型号(这是简化版) 我想创建一个查询,该查询将生成一个具有最多事件的用户列表,其中其所有从属事件项的rev1和rev2均不为空或null,且active=True 我知道我可以通过迭代用户列表,然后检查他们的所有事件,以匹配rev1、rev2、和active标准,然后返回这些事件,但这对数据库来说是个沉重的负担。有什么建议吗 谢谢 你的模型被破坏了,但这应该以一种更干净的方式总结你所做的事情 class S

我正试图以最有效的方式在Django中执行一个相当复杂的查询,但我不知道如何开始。我有这些型号(这是简化版)

我想创建一个查询,该查询将生成一个具有最多事件的用户列表,其中其所有从属事件项的
rev1
rev2
均不为空或null,且
active=True

我知道我可以通过迭代用户列表,然后检查他们的所有事件,以匹配
rev1
rev2
、和
active
标准,然后返回这些事件,但这对数据库来说是个沉重的负担。有什么建议吗


谢谢

你的模型被破坏了,但这应该以一种更干净的方式总结你所做的事情

class Status(models.Model):
    status = models.CharField(max_length=200)

class User(models.Model):
    name = models.CharField(max_length=200)
    events = models.ManyToManyField('Event')

class Event(models.Model):
    rev1 = models.ForeignKey(Status, related_name='rev1', blank=True, null=True)
    rev2 = models.ForeignKey(Status, related_name='rev2', blank=True, null=True)
    active = models.BooleanField()
以及查询

User.objects.filter(events\uu active=True).exclude(Q(events\uu rev1=None)| Q(events\uu rev2=None)).注释(num\u events=Count('events')).排序依据('-num\u events')

这将返回一个用户列表,按其集合中的事件数排序


有关更多信息,请查看字段。

您可以尝试以下方法:

EventItem.objects.exclude(rev1=None).exclude(rev2=None).filter(active=True).values_list('event__user', flat=True)
这将为您提供一个用户id的平面列表,其中每个id的频率是用户拥有多少个EventItem对象

您可能可以做得更好,并使用
.annotate()
将其集成到查询中,但我现在不知道如何操作

我想创建一个查询,该查询将生成一个拥有最多事件的用户列表,其中所有依赖事件项的rev1和rev2均不为空或null,且active=True

首先,您需要始终具有这种类型的
EventItem
Event
对象

events = Event.objects.filter(active=True)
events = events.exclude(eventitem__rev1__isnull=True)
events = events.exclude(eventitem__rev1='')
events = events.exclude(eventitem__rev2__isnull=True)
events = events.exclude(eventitem__rev2='')
另外,您没有指定是否要处理没有
EventItem
Event
对象。您可以使用以下选项过滤掉这些内容:

events = events.exclude(eventitem__isnull=True)
请注意,
事件
可能包含大量重复项。如果愿意,您可以插入一个
events.distinct()
,但只有在需要时才应该这样做

拥有这些对象后,现在可以提取所需的
User
对象:

users = User.objects.filter(event__in=events)
请注意,在某些数据库后端,*ahem*MySQL*ahem*,您可能会发现
.filter(field\uu in=QuerySet)
模式是无效的。在这种情况下,代码应为:

users = User.objects.filter(event__in=list(events.values_list('pk', flat=True)))
然后,您可以按所附
事件
对象的数量排序:

from django.db.models import Count
active_users = users.annotate(num_events=Count('event')).order_by('-num_events')

谢谢,Roman,但这与我的问题不太相符-我没有使用
manytomy
字段-任何关于我如何使用当前模型的想法。我最初确实忘记了
EventItem
中的“event”字段,但我添加了它。谢谢这是一个极好的答案,回答了从“为……类型的查询规划模型的最佳方式是什么”开始的问题。不幸的是@JonoBacon没有问这个问题。也许下次吧?
from django.db.models import Count
active_users = users.annotate(num_events=Count('event')).order_by('-num_events')