从 Django 中的方法中获取结果

问题描述

我的 Django 应用程序 ('crisismode') 有两个模型:事件和操作

我想显示与这些事件相关的事件和操作。对于每个事件,我只想显示活动的动作,所以我使用了一个方法(activactions)。

如何预取这些动作?

class Event(models.Model):
    description = models.CharField(max_length=1000,blank=True)
    active = models.BooleanField(default=True)

    def activeactions(self):
        actions = Action.objects.filter(event=self,active=True)
        if actions:
            return Action.objects.filter(event=self,active=True)
        else:
            return None

class Action(models.Model):
    description = models.CharField(max_length=1000)
    active = models.BooleanField(default=True)
    event = models.ForeignKey(Event,on_delete=models.SET_NULL,related_name="actionsforevent",null=True,blank=True)

我执行以下查询

events = Event.objects.filter(crisis=crisis,active=True).prefetch_related('actionsforevent')

但是 django-debug-toolbar 告诉我有多个查询

FROM "crisismode_action"
 WHERE ("crisismode_action"."active" = true AND "crisismode_action"."event_id" = 323)
 ORDER BY "crisismode_action"."order" ASC,"crisismode_action"."id"
 ASC 10 similar queries.  Duplicated 2 times.

解决方法

首先,我将说明有关 prefetch_related 的文档的一部分:

prefetch_related,另一方面,对每个关系进行单独的查找,并在 Python 中进行“连接”。

意味着预取相关将进行多个查询。继续查看您的问题,您有一个方法 activeactions,您可以在其中尝试获取事件的活动操作。您还尝试使用与 .prefetch_related('actionsforevent') 相关的预取。这不像您期望的那样工作,因为您所做的预取与您的方法调用是分开的。您也不会在此预取中进行过滤。

对于您的使用,我相信您只想预取字段 activeTrue 的操作。您可以使用可以接受查询集的 Prefetch object 来做到这一点:

from django.db.models import Prefetch

events = Event.objects.filter(
    crisis=crisis,active=True
).prefetch_related(
    Prefetch(
        'actionsforevent',queryset=Action.objects.filter(active=True),to_attr='active_actions'
    )
)

我们使用 to_attr 参数来指定我们想要自定义属性 active_actions 上的结果。

现在我们可以简单地使用 event.active_actions 访问预取的活动操作。例如:

for event in events:
    for action in event.active_actions:
        print(action.description)