【问题标题】:Fetching results from a method in Django从 Django 中的方法获取结果
【发布时间】:2021-06-04 19:02:55
【问题描述】:

我的 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.

【问题讨论】:

  • 你到底想做什么?仅预取active 字段为True 的那些操作? (预取相关也会进行多次查询)
  • 是的,只有那些活动字段为 True 的操作。

标签: django foreign-keys django-queryset


【解决方案1】:

首先我要说明文档中关于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)

【讨论】:

  • 完美运行!非常感谢您的回答
猜你喜欢
  • 2014-01-19
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 2020-05-08
  • 1970-01-01
  • 2018-01-30
  • 2016-07-13
相关资源
最近更新 更多