Django模板无法访问上下文对象title属性仅可读取id属性问题
问题根因
你传入模板上下文的listings是WatchedListing中间表的QuerySet,并非商品模型Listing的结果集:
WatchedListing表本身只存储用户和商品的收藏关联关系,自带字段只有主键id、关联用户的外键owner、关联商品的外键watched_listing,没有定义title字段。Django模板访问对象不存在的属性时会默认渲染空值、不抛出异常,这就是标题位置显示空白的直接原因。- 你写
{{ listing.id }}能正常输出,取到的是WatchedListing关联记录自身的主键ID,不是对应商品的ID。之前列表跳转能正常进入商品详情页,只是测试阶段数据量小,关联记录ID和对应商品ID刚好数值重合,属于巧合,后续数据量上来后跳转逻辑必然出错。
修复方案
二选一即可:
方案1:最小改动,调整模板取值逻辑
循环中拿到的是WatchedListing实例,需要通过外键字段watched_listing拿到关联的商品对象,再读取商品属性,修改watchlist.html的循环块即可:
{% for watched_item in listings %} <a href="{% url 'listing' listing_id=watched_item.watched_listing.id %}"> <li>{{ watched_item.watched_listing.title }}</li> </a> {% endfor %}
建议把循环变量名从listing改成watched_item这类语义化名称,避免和真实的商品对象混淆。
方案2:调整视图查询逻辑,直接返回商品结果集
如果不想在模板里写多层属性调用,可以直接在视图层跨表查询,拿到当前用户收藏的所有Listing对象,修改watchlist_view:
@login_required def watchlist_view(request): # 利用外键related_name跨表筛选,直接取收藏的商品实例 listings = models.Listing.objects.filter(watched_listings__owner=request.user) return render(request, "auctions/watchlist.html", {"listings": listings})
改完之后你原有模板里的{{ listing.title }}、跳转用的listing.id都可以正常工作,不需要调整模板代码。
额外代码优化
你当前add_to_watchlist视图里判断重复收藏的逻辑性能很差,不需要把用户所有收藏记录全查出来再判断,直接用exists()做存在性查询即可,减少数据库查询开销:
@login_required def add_to_watchlist(request, listing_id): listing = models.Listing.objects.get(pk=listing_id) # 直接查询是否存在对应关联记录,不需要拉取全量数据 if models.WatchedListing.objects.filter(owner=request.user, watched_listing=listing).exists(): messages.error(request, "This item is already on your watchlist.") return redirect(reverse('listing', args=[listing.pk])) watchlist = WatchedListing() watchlist.owner = request.user watchlist.watched_listing = listing watchlist.save() messages.success(request, "Added to your watchlist!") return redirect(reverse('listing', args=[listing.pk]))
内容的提问来源于stack exchange,提问作者Brett
相关产品推荐
相关产品推荐

