You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django技术问询:如何获取每种化学品的最新价格并在模板中正确渲染展示

解决Django中化学品最新价格的关联展示问题

你的问题出在视图查询逻辑和模板渲染的关联上:当前你获取的qs是所有符合条件的最新价格记录的集合,但模板里直接调用{{ qs.price }}时,Django会默认取查询集的第一个对象的价格,所以所有化学品行都显示同一个值。下面是两种更优雅的解决方案,让你能在模板里直接把化学品和它的最新价格对应起来。

方案一:用Subquery给Chemicals查询集添加最新价格字段

这种方法会直接把每个化学品的最新价格作为字段附加到Chemicals对象上,模板渲染时非常直观。

首先在视图里导入需要的模块:

from django.db.models import Subquery, OuterRef
from django.shortcuts import get_object_or_404, render

然后修改视图函数:

def price_list(request,pk):
    supplier = get_object_or_404(Suppliers, pk=pk)
    
    # 子查询:获取当前化学品的最新价格(按日期倒序取第一条的price值)
    latest_price_subquery = Prices.objects.filter(
        id_chemical=OuterRef('pk')  # 关联外部查询的Chemicals主键
    ).order_by('-price_date').values('price')[:1]
    
    # 给Chemicals查询集添加latest_price字段,关联子查询结果
    chemicals_list = Chemicals.objects.filter(id_supplier=pk).annotate(
        latest_price=Subquery(latest_price_subquery)
    )
    
    context = {'supplier': supplier, 'chemicals_list': chemicals_list}
    return render(request, "chemicals/price_list.html", context)

对应的模板代码简化为:

<tbody>
{% for chemical in chemicals_list %}
<tr>
<td><a href="{% url 'chemicals:single-product' pk=chemical.id_chemical %}">{{ chemical.description }}</a></td>
<td>{{ chemical.latest_price|default:"无价格" }}</td>  <!-- 处理可能没有价格的情况 -->
<td>{{ chemical.cov }}</td>
{% endfor %}
</tbody>

方案二:用Prefetch预取最新价格记录

如果需要获取价格的更多字段(比如价格日期),可以用Prefetch来预取每个化学品的最新价格记录:

修改视图函数:

from django.db.models import Prefetch
from django.shortcuts import get_object_or_404, render

def price_list(request,pk):
    supplier = get_object_or_404(Suppliers, pk=pk)
    
    # 定义预取规则:按日期倒序取每个化学品的第一条价格记录
    latest_price_prefetch = Prefetch(
        'prezzo',  # 对应Chemicals模型中Prices的related_name
        queryset=Prices.objects.order_by('-price_date')[:1],
        to_attr='latest_price_records'  # 自定义属性名,存储预取的记录
    )
    
    # 预取最新价格到Chemicals查询集
    chemicals_list = Chemicals.objects.filter(id_supplier=pk).prefetch_related(
        latest_price_prefetch
    )
    
    context = {'supplier': supplier, 'chemicals_list': chemicals_list}
    return render(request, "chemicals/price_list.html", context)

模板里可以这样渲染:

<tbody>
{% for chemical in chemicals_list %}
<tr>
<td><a href="{% url 'chemicals:single-product' pk=chemical.id_chemical %}">{{ chemical.description }}</a></td>
<td>
  {% if chemical.latest_price_records %}
    {{ chemical.latest_price_records.0.price }}
    <small>({{ chemical.latest_price_records.0.price_date }})</small>
  {% else %}
    无价格
  {% endif %}
</td>
<td>{{ chemical.cov }}</td>
{% endfor %}
</tbody>

为什么你的原代码会出问题?

你原视图中的qs是筛选出了该供应商下所有化学品的最新价格记录,但模板循环时,你没有把当前chemical和qs中对应的价格记录关联起来——直接调用{{ qs.price }}相当于取qs这个查询集的第一个对象的价格,所以所有行都显示同一个值。

内容的提问来源于stack exchange,提问作者Stefano Ferrari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 22:37:47