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
相关产品推荐
相关产品推荐

