Django-Bootstrap循环遍历异常:模态框仅显示首个对象属性
问题根源:重复的模态框选择器
嘿,这绝对不是Bootstrap的锅——是你代码里的一个小疏忽:循环里的所有模态框都使用了同一个类名.bd-example-modal-xl作为data-target,Bootstrap在匹配模态框时只会找到第一个符合选择器的元素,所以不管你点哪张缩略图,都会弹出第一个模态框,自然显示的是第一个画作的属性。
解决方案1:给每个模态框分配唯一ID
最简单的修复方式是利用每个painting对象的唯一标识(比如pk),给每个模态框生成独一无二的ID,让缩略图的data-target精准指向对应的模态框。修改后的代码如下:
{% for painting in artist.paintings.all %} <!-- 缩略图:指向当前画作的专属模态框 --> <img class="painting" src="{{ painting.Gemälde.url }}" data-toggle="modal" data-target="#painting-modal-{{ painting.pk }}" /> <!-- 专属模态框:ID包含当前画作的pk --> <div class="modal fade bd-example-modal-xl" id="painting-modal-{{ painting.pk }}" tabindex="-1" role="dialog" aria-labelledby="modal-title-{{ painting.pk }}" aria-hidden="true"> <div class="modal-dialog modal-xl" role="document"> <div class="modal-content"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h5 class="modal-title mx-auto" id="modal-title-{{ painting.pk }}">{{ painting.Bildname }}</h5> <img class="painting-active" src="{{ painting.Gemälde.url }}"> <div class="modal-footer"> <p class="mx-auto"> {{ painting.Bildtechnik }}, {{ painting.Erstelldatum }}, {{ painting.Bildmaße_in_cm }}cm {% if painting.Bildpreis != 0 %} , {{ painting.Bildpreis }} {% endif %} </p> </div> </div> </div> </div> {% endfor %}
这里做了几个关键调整:
- 把循环变量名改成单数
painting(更符合语义) - 给每个模态框的ID加上
painting.pk,确保唯一 - 缩略图的
data-target对应到当前画作的模态框ID - 模态框的
aria-labelledby属性也用了唯一的标题ID,符合无障碍规范
解决方案2:用单个模态框动态加载内容(更高效)
如果你的画作数量很多,生成一堆模态框会增加DOM体积,推荐用一个模态框+JavaScript动态填充内容的方式,性能更好:
第一步:在循环外写一个空的模态框模板
<div class="modal fade bd-example-modal-xl" id="painting-modal" tabindex="-1" role="dialog" aria-labelledby="painting-modal-title" aria-hidden="true"> <div class="modal-dialog modal-xl" role="document"> <div class="modal-content"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h5 class="modal-title mx-auto" id="painting-modal-title"></h5> <img class="painting-active" src=""> <div class="modal-footer"> <p class="mx-auto" id="painting-modal-details"></p> </div> </div> </div> </div>
第二步:给循环里的缩略图添加自定义数据属性
把画作的所有需要展示的属性存在图片的data-*属性里:
{% for painting in artist.paintings.all %} <img class="painting" src="{{ painting.Gemälde.url }}" data-toggle="modal" data-target="#painting-modal" data-image-url="{{ painting.Gemälde.url }}" data-title="{{ painting.Bildname }}" data-technique="{{ painting.Bildtechnik }}" data-date="{{ painting.Erstelldatum }}" data-size="{{ painting.Bildmaße_in_cm }}" data-price="{% if painting.Bildpreis != 0 %}{{ painting.Bildpreis }}{% endif %}" /> {% endfor %}
第三步:用JavaScript动态填充模态框内容
监听模态框的show.bs.modal事件,从触发的图片元素里读取数据,填充到模态框中:
$('#painting-modal').on('show.bs.modal', function (event) { // 获取触发模态框的图片元素 const triggerBtn = $(event.relatedTarget); // 读取自定义数据属性里的内容 const imageUrl = triggerBtn.data('image-url'); const title = triggerBtn.data('title'); const technique = triggerBtn.data('technique'); const date = triggerBtn.data('date'); const size = triggerBtn.data('size'); const price = triggerBtn.data('price'); // 获取模态框元素,填充内容 const modal = $(this); modal.find('#painting-modal-title').text(title); modal.find('.painting-active').attr('src', imageUrl); // 拼接详情文本 let detailsText = `${technique}, ${date}, ${size}cm`; if (price) { detailsText += `, ${price}`; } modal.find('#painting-modal-details').text(detailsText); });
这种方法只需要一个模态框,不管有多少画作都不会增加DOM负担,尤其适合大量数据的场景。
内容的提问来源于stack exchange,提问作者Dariun
相关产品推荐
相关产品推荐

