Django中Ajax请求视图里return render(...)无法跳转页面的问题
问题:点击按钮创建聊天室后无法跳转至聊天页面
点击页面按钮调用Ajax请求创建聊天室,后台已成功生成Thread记录,但视图中return render(request, 'chat/chatroom.html')无法打开目标页面,无任何报错信息。
相关代码
HTML代码
<button type="submit" id="chat-button" value="{{advertisement.author.id}}">Write to the author</button> <script> $(document).on('click', '#chat-button', function (e) { e.preventDefault(); $.ajax({ type: 'POST', url: '{% url "main_app:create-chat" %}', data: { send_to_id: $('#chat-button').val(), csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(), action: 'post' }, success: function (json) { }, error: function (xhr, errmsg, err) { } }); }) </script>
views.py代码
from django.contrib.auth import get_user_model from django.shortcuts import render, redirect, get_object_or_404 from django.db.models import Q from django.utils.decorators import method_decorator from django.views import View from django.views.decorators.csrf import csrf_exempt from chat.models import Thread User = get_user_model() @method_decorator(csrf_exempt, name='dispatch') class CreateChat(View): def post(self, request): send_to_id = int(request.POST.get('send_to_id')) send_to = User.objects.get(id=send_to_id) auth_user = request.user final_q = Q(Q(first_person=send_to) & Q(second_person=auth_user)) \ | Q(Q(first_person=auth_user) & Q(second_person=send_to)) thread = Thread.objects.filter(final_q) if not thread: Thread.objects.create(first_person=auth_user, second_person=send_to) return render(request, 'chat/chatroom.html')
urls.py代码
app_name = 'main_app' urlpatterns = [ ... path('create_chat', CreateChat.as_view(), name='create-chat') ]
问题原因
Ajax是异步HTTP请求,服务器返回的HTML内容只会传递到success回调函数中,浏览器不会自动加载该内容作为新页面——它仅在后台接收数据,不会主动替换当前页面或发起跳转。因此你当前的写法中,视图返回的chatroom.html内容只是被Ajax接收,但未做任何处理,自然看不到页面跳转效果。
解决方案
方案1:调整Ajax逻辑,处理返回结果实现跳转
方式A:视图返回聊天室URL,前端主动跳转
修改views.py,创建Thread后返回该聊天室的访问URL:
from django.http import JsonResponse @method_decorator(csrf_exempt, name='dispatch') class CreateChat(View): def post(self, request): send_to_id = int(request.POST.get('send_to_id')) send_to = User.objects.get(id=send_to_id) auth_user = request.user final_q = Q(Q(first_person=send_to) & Q(second_person=auth_user)) | Q(Q(first_person=auth_user) & Q(second_person=send_to)) # 用first()获取单个对象,避免返回QuerySet thread = Thread.objects.filter(final_q).first() if not thread: thread = Thread.objects.create(first_person=auth_user, second_person=send_to) # 假设聊天室页面的URL格式为/chat/<thread_id>/,根据实际路由调整 chat_url = f'/chat/{thread.id}/' return JsonResponse({'chat_url': chat_url})
修改前端JS,在success回调中跳转到返回的URL:
$(document).on('click', '#chat-button', function (e) { e.preventDefault(); $.ajax({ type: 'POST', url: '{% url "main_app:create-chat" %}', data: { send_to_id: $('#chat-button').val(), csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(), action: 'post' }, success: function (json) { // 跳转到聊天室页面 window.location.href = json.chat_url; }, error: function (xhr, errmsg, err) { console.error(errmsg); // 打印错误信息便于调试 } }); })
方式B:用返回的HTML替换当前页面内容(仅适用于局部刷新场景)
如果不需要跳转页面,而是替换当前页面的部分内容,可以在success回调中处理返回的HTML:
success: function(response) { // 替换整个页面body内容 $('body').html(response); // 或替换指定容器,比如页面中有<div id="chat-container"></div> // $('#chat-container').html(response); }
方案2:放弃Ajax,使用普通表单提交(更简洁)
如果需求仅为创建聊天室后跳转页面,完全可以不用Ajax,直接用表单提交,服务器的redirect或render会直接生效:
修改HTML,将按钮包裹在表单中:
<form method="POST" action="{% url 'main_app:create-chat' %}"> {% csrf_token %} <input type="hidden" name="send_to_id" value="{{advertisement.author.id}}"> <button type="submit" id="chat-button">Write to the author</button> </form>
修改views.py,创建Thread后跳转至聊天室页面(推荐用redirect,符合HTTP规范):
from django.shortcuts import redirect @method_decorator(csrf_exempt, name='dispatch') class CreateChat(View): def post(self, request): send_to_id = int(request.POST.get('send_to_id')) send_to = User.objects.get(id=send_to_id) auth_user = request.user final_q = Q(Q(first_person=send_to) & Q(second_person=auth_user)) | Q(Q(first_person=auth_user) & Q(second_person=send_to)) thread = Thread.objects.filter(final_q).first() if not thread: thread = Thread.objects.create(first_person=auth_user, second_person=send_to) // 假设聊天室页面的URL名称为'chat:room',需传递thread.id参数,根据实际路由调整 return redirect('chat:room', thread_id=thread.id) // 若需直接渲染页面,也可保留return render,但redirect更推荐 // return render(request, 'chat/chatroom.html', {'thread': thread})
内容的提问来源于stack exchange,提问作者Dmytro
相关产品推荐
相关产品推荐

