Django:在一个查询中加入两个表
Django: Join two tables in a single query
在我的模板中,我有一个 table,我想用来自两个使用外键的不同 table 的数据填充它。
我在谷歌搜索时找到的解决方案是使用 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 获取价格,但它也使表 1 中的数据 (item.fruit) 消失。如果我删除值字段,表 1 会相应地填充。
有人对我做错了什么有任何反馈吗?
谢谢
如果你利用.values(…)
[Django-doc], then you retrieve a queryset of dictionaries, that only contains the values specified. This is not a good idea. Not only because as you found out, it wiill thus no longer use the values in the model, but you will "erode" the model layer as well: it is no longer a Table1
object, but a dictionary. Which is a form of a primitive obsession antipattern [refactoring.guru].
您可以使用 .annotate(…)
[Django-doc] 为由此查询集产生的元素添加额外的属性:
from django.db.models import F
data = Table1.objects.filter(date=today).annotate(
<b>table2__price=F('table2__price')</b>
)
如果从 Table1
到 Table2
有 ForeignKey
(或 OneToOneField
),您可以 select [=16= 的列] 在与 .select_related(…)
[Django-doc]:
相同的查询中
data = Table1.objects.filter(date=today)<b>.select_related('table2')</b>
在模板中,您可以使用:
{{ item.fruit }}
{{ item<b>.table2.price</b> }}
{{ item<b>.table2.other_attr</b> }}
.select_related(…)
部分不是绝对必要的,但如果没有它,它将对每个 项目进行额外的查询 ,因此这将产生一个 N+1 题.
在我的模板中,我有一个 table,我想用来自两个使用外键的不同 table 的数据填充它。
我在谷歌搜索时找到的解决方案是使用 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 获取价格,但它也使表 1 中的数据 (item.fruit) 消失。如果我删除值字段,表 1 会相应地填充。
有人对我做错了什么有任何反馈吗?
谢谢
如果你利用.values(…)
[Django-doc], then you retrieve a queryset of dictionaries, that only contains the values specified. This is not a good idea. Not only because as you found out, it wiill thus no longer use the values in the model, but you will "erode" the model layer as well: it is no longer a Table1
object, but a dictionary. Which is a form of a primitive obsession antipattern [refactoring.guru].
您可以使用 .annotate(…)
[Django-doc] 为由此查询集产生的元素添加额外的属性:
from django.db.models import F
data = Table1.objects.filter(date=today).annotate(
<b>table2__price=F('table2__price')</b>
)
如果从 Table1
到 Table2
有 ForeignKey
(或 OneToOneField
),您可以 select [=16= 的列] 在与 .select_related(…)
[Django-doc]:
data = Table1.objects.filter(date=today)<b>.select_related('table2')</b>
在模板中,您可以使用:
{{ item.fruit }}
{{ item<b>.table2.price</b> }}
{{ item<b>.table2.other_attr</b> }}
.select_related(…)
部分不是绝对必要的,但如果没有它,它将对每个 项目进行额外的查询 ,因此这将产生一个 N+1 题.