【问题标题】:Django: Join two tables in a single queryDjango:在一个查询中连接两个表
【发布时间】:2020-12-05 20:38:59
【问题描述】:

在我的模板中,我有一个表,我想用两个使用外键的不同表中的数据填充该表。

我在谷歌搜索时找到的解决方案是使用 values(),下面是我的查询集示例:

data = Table1.objects.all().filter(date=today).values('table2__price')

我的模板

    {% for item in data %}
        <tr class="original">
          <td>{{ item.fruit }}</td>
          <td>{{ item.table2__price }}</td>
        </tr>
    {% endfor %}

它确实从 table2 获取价格,但它也使 Table1 中的数据 (item.fruit) 消失。如果我删除值字段,Table1 会相应地填充。

有人对我做错了什么有任何反馈吗?

谢谢

【问题讨论】:

  • 你不需要all(),你可以写Table1.objects.filter(...)。

标签: django django-views django-queryset


【解决方案1】:

如果您使用.values(…) [Django-doc],那么您将检索字典 的查询集,该查询集仅包含指定的值。这不是一个好主意。不仅因为您发现它不再使用模型中的值,而且您还将“侵蚀”模型层:它不再是 Table1 对象,而是一本字典。这是primitive obsession antipattern [refactoring.guru] 的一种形式。

您可以使用.annotate(…) [Django-doc] 为由此查询集产生的元素添加额外的属性:

from django.db.models import F

data = Table1.objects.filter(date=today).annotate(
    table2__price=F('table2__price')
)

如果从Table1 到Table2 之间存在ForeignKey(或OneToOneField),则可以在与.select_related(…) [Django-doc] 相同的查询中选择Table2 的列:

data = Table1.objects.filter(date=today)<b>.select_related('table2')</b>

在模板中,然后可以使用:

{{ item.fruit }}
{{ item.table2.price }}
{{ item.table2.other_attr }}

.select_related(…) 部分不是绝对必要的,但没有它,它会产生一个额外的查询每个 项,因此这将产生一个N+1 问题。

【讨论】:

  • 这似乎有效!如果我想说来自 table2 中多列的数据,这会起作用吗?或者是否有其他方法可以做到这一点,以防有一些“最佳实践”:-)
  • @massideux: 有没有从Table1 到Table2 的ForeignKey?
  • 是的,我试过了,只需在 annotate() 中添加另一列,一切都会顺利进行。非常感谢 WillEm! :)
猜你喜欢
  • 2016-12-05
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 2014-11-07
相关资源
最近更新 更多