Django+jQuery发送POST请求后DIV内messages数据和页面无法更新问题
问题核心原因
- 你之前
load方法失效的核心原因:该方法会发起全新的GET请求拉取当前页面,请求没有携带你选中的userId参数,服务端返回的还是默认第一个用户的消息,自然不会更新为你选中用户的内容。 - 按钮点击的POST请求默认没有携带Django要求的CSRF令牌,也是潜在的请求失效原因。
方案1:最优解-局部只更新消息区域
不需要刷新整个页面,只返回消息渲染片段替换即可,性能最优。
步骤1:拆分消息模板
把消息循环的代码单独抽成一个子模板,存为templates/_chat_messages.html:
{% for o in messages %} {% if o.to_id.id != 2 %} <div class="d-flex justify-content-start mb-4"> <div class="img_cont_msg"> <!-- 原有图片内容 --> </div> <div class="msg_cotainer"> {{o.message}} <!-- <span class="msg_time">{{o.time}}</span> --> </div> </div> {% else %} <div class="d-flex justify-content-end mb-4"> <div class="msg_cotainer_send"> {{o.message}} <!-- <span class="msg_time_send">{{o.time}}</span> --> </div> <div class="img_cont_msg"> <!-- 原有图片内容 --> </div> </div> {% endif %} {% endfor %}
主页面psych.html中原来放消息循环的位置,替换为引入子模板的代码,确保外层有id为messageDiv的容器:
<div id="messageDiv"> {% include '_chat_messages.html' %} </div>
步骤2:修改后端视图
判断是AJAX请求时,只返回消息片段,不用渲染整个页面:
def your_view(request): m = Message.objects.filter(to_id=2).order_by('-id') users = {} for i in m: if users.get(i.from_id.username) == None: users[i.from_id.username] = User.objects.get(id=i.from_id.id) users = list(users.values()) default_user_id = users[0].id if users else None if request.method == 'POST': user_id = request.POST.get('userId') send=Message.objects.filter(from_id=user_id,to_id=2) rec=Message.objects.filter(from_id=2,to_id=user_id) messages=sorted(chain(rec, send),key=lambda instance: instance.id,reverse=True) # 识别AJAX请求则只返回消息片段 if request.is_ajax(): return render(request, '_chat_messages.html', {"messages": messages}) return render(request,'psych.html',{"users":users, "messages":list(messages)}) # GET请求走原有逻辑 send=Message.objects.filter(from_id=default_user_id,to_id=2) rec=Message.objects.filter(from_id=2,to_id=default_user_id) messages=sorted(chain(rec, send),key=lambda instance: instance.id,reverse=True) return render(request,'psych.html',{"users":users, "messages":list(messages)})
步骤3:修改前端JS代码
先全局配置CSRF令牌,再直接替换消息区域内容:
// 全局配置CSRF,避免每次请求单独传参 function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } const csrftoken = getCookie('csrftoken'); $.ajaxSetup({ headers: { 'X-CSRFToken': csrftoken } }); // 点击用户按钮的请求逻辑 function newUser(id){ $.ajax({ type: 'POST', url:'/psych.html/', data:{ userId:id, }, success: function(data){ // 直接用返回的消息片段替换原有内容 $('#messageDiv').html(data); } }) }
方案2:整页替换方案
如果不想改模板结构,直接用服务端返回的完整页面替换当前页面内容即可,修改newUser的success回调:
function newUser(id){ $.ajax({ type: 'POST', url:'/psych.html/', data:{ userId:id, csrfmiddlewaretoken: getCookie('csrftoken') }, success: function(data){ // 直接替换整个页面的HTML内容 document.documentElement.innerHTML = data; // 如果只需要替换正文区域也可以写:$('body').html(data); } }) }
内容的提问来源于stack exchange,提问作者مهند حجي
相关产品推荐
相关产品推荐

