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

Django模板循环中AJAX仅获取首个元素ID的问题求助

问题排查结果

出现这个问题的核心原因是循环渲染时大量重复的通用类名、固定ID导致jQuery选择器全局匹配时永远命中第一条帖子对应的DOM元素,具体有3个直接诱因:

  • 所有帖子的编辑弹窗都用了固定id="edit"、相同的通用类modal-edit、textarea_edit,没有和帖子主键做唯一绑定,用$('.textarea_edit')这类全局选择器取值时,默认返回DOM树中第一个匹配的元素,也就是第一条帖子的输入框内容
  • 列表里的[Edit]按钮没有绑定对应帖子弹窗的触发逻辑,原代码里a标签直接指向帖子详情页路由,没有配置data属性唤起当前帖子专属的编辑弹窗
  • JS点击回调没有基于当前点击的元素做相对DOM查找,所有取值、弹窗操作都是全局匹配元素,自然永远拿到第一条的数据
修复方案

1. 修改Django模板循环代码

给每个弹窗、触发按钮绑定帖子主键做唯一标识,配置正确的弹窗触发属性,修复后代码如下:

{% for post in paginated_posts %}
<div style="padding: 10px;" id="{{post.id}}">
    <div style="padding: 10px; border: 1px solid;">
    <p>
    <h4><a href="{% url 'post_view' post.pk %}">{{ post.title }}</a></h4>
    </p>
    <p style="display: inline-flex;">
      {% if post.author.profile.id %}
    by: <span style="font-weight: bold;"><a href="{% url 'profile_class' post.author.profile.id %}">&nbsp; {{ post.author }} &nbsp;</a></span>
    {% else %}
    by: <span style="font-weight: bold;">&nbsp; {{ post.author }} &nbsp;</span>    
    {% endif %}
    on {{ post.creation_date }}
    </p>
    <h5 class="card-text post-object-content{{post.id}}">{{ post.post_text }}</h5>
    
<!-- Edit -->
{% if user.is_authenticated %}
{% if user.id == post.author.id %}

<!-- Button modal edit 新增弹窗触发属性,绑定对应帖子的唯一弹窗ID -->
<small><a href="javascript:void(0)" data-toggle="modal" data-target="#edit-{{ post.pk }}">[Edit]</a></small>

<!-- Modal EDIT 给弹窗ID加post主键后缀,保证唯一 -->
<div class="modal fade modal-edit" id="edit-{{ post.pk }}" role="dialog">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content new-post-content">
      <div class="modal-header">
        <h5 class="modal-title">Edit post {{ post.id }}</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
          <form method=post action="{% url 'edit' post.pk %}">
              {% csrf_token %}
              <textarea rows="10" class="form-control textarea_edit textarea-edit-{{ post.pk }}" name="textarea">{{post.post_text}}</textarea>
              <br>
              <div class="modal-footer">
                  <button class="btn btn-primary save editfunction" data-post_pk="{{ post.pk }}" type="submit" value="Save">Submit</button>
              </div>
          </form>
      </div>
    </div>
  </div>
</div>
{% endif %}
{% endif %}
</div>
</div>
{% endfor %}

注意:原模板代码末尾少了两个{% endif %}和对应div闭合标签,上面代码已经补全,否则Django模板渲染会报错。

2. 修改JS逻辑

所有元素查找都基于当前点击的按钮做相对定位,不要用全局选择器直接搜通用类名,修复后代码如下:

//Edit
$('.editfunction').click(function(e){
        e.preventDefault()
        // 先拿到当前按钮所属的弹窗DOM
        const currentModal = $(this).closest('.modal-edit');
        var post_pk = $(this).data("post_pk");
        // 从当前弹窗里找输入框取值,不会拿到其他帖子的内容
        var content = currentModal.find('.textarea_edit').val();

        $.ajax({
        type: "POST",
        url: `/post/${post_pk}/edit`,
        data: {
            csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
            post_id: post_pk,
            textarea: content
        },
        success: function(data) {
            // 只关闭当前操作的弹窗
            currentModal.modal('hide')
            // 更新对应帖子的展示内容
            $(`.post-object-content${post_pk}`).html(content)
        }
        })
    })
验证点

改完后可以先在浏览器右键检查元素,确认每个帖子的编辑弹窗ID都带不同的post主键,点击[Edit]按钮唤起的是当前帖子对应的弹窗,提交时可以在浏览器控制台Network面板看请求参数里的textarea值是不是当前编辑的内容即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:15:32