使用Django REST Framework通过Ajax登录返回HTML而非JSON问题求助
哦,我懂你遇到的问题了——你用的/api-auth/login/其实是DRF自带的可浏览API登录页面,它本来就是返回HTML的,根本不是给Ajax调用的JSON接口!这就是核心问题所在。
下面给你两个针对性的解决方案,看你更倾向用JWT还是Session认证:
方案1:用JWT自带的JSON登录接口(推荐,因为你已经配置了JWT认证)
rest_framework_jwt已经为你封装好了现成的JSON登录端点,只需要把它加到URL配置里就行:
第一步:配置URL
在你的urls.py中添加:
from rest_framework_jwt.views import obtain_jwt_token urlpatterns = [ # ... 你的其他URL配置 path('api-token-auth/', obtain_jwt_token), # 这个就是专门的JSON登录接口 ]
第二步:修改Ajax请求
把请求指向新的端点,并且确保请求格式正确:
$.ajax({ url: '/api-token-auth/', method: 'POST', contentType: 'application/json', // 必须指定这个,告诉后端你发的是JSON数据 data: JSON.stringify({ username: $('#username').val(), // 替换成你的用户名输入框选择器 password: $('#password').val() // 替换成你的密码输入框选择器 }), success: function(response) { // 登录成功后会返回JWT token,比如 response.token console.log('登录成功,Token:', response.token); // 把Token存在localStorage里,后续请求带上它 localStorage.setItem('jwt_token', response.token); // 之后的API请求可以在headers里加:'Authorization': 'JWT ' + localStorage.getItem('jwt_token') }, error: function(xhr) { // 错误信息会以JSON返回,比如用户名密码错误 console.error('登录失败:', xhr.responseJSON); } });
方案2:自定义Session登录接口(如果你想用Session认证)
如果更倾向于用SessionAuthentication,你需要自己写一个返回JSON的登录视图,因为DRF的默认登录页不支持这个场景:
第一步:写登录视图
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.contrib.auth import authenticate, login class JSONSessionLoginView(APIView): # 登录接口不需要前置认证 permission_classes = [] def post(self, request): username = request.data.get('username') password = request.data.get('password') # 验证用户身份 user = authenticate(request, username=username, password=password) if user: login(request, user) return Response({ 'message': '登录成功', 'user_info': { 'username': user.username, 'email': user.email } }, status=status.HTTP_200_OK) else: return Response({ 'error': '用户名或密码错误' }, status=status.HTTP_401_UNAUTHORIZED)
第二步:配置URL
path('api-session-login/', JSONSessionLoginView.as_view()),
第三步:修改Ajax请求
这里可以用form-data格式(不用转JSON),注意要带上CSRF token(Session认证需要):
// 先获取CSRF token(Django默认存在cookie里) 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; } $.ajax({ url: '/api-session-login/', method: 'POST', headers: { 'X-CSRFToken': getCookie('csrftoken') // 必须带上这个 }, data: { username: $('#username').val(), password: $('#password').val() }, success: function(response) { console.log('登录成功:', response); // Session认证下,后续请求会自动带上cookie,不用手动处理token }, error: function(xhr) { console.error('登录失败:', xhr.responseJSON); } });
几个小提醒
- 如果你的前端和后端是跨域名的,还需要配置Django的CORS(不过同域名下不用管)
- 检查你的
REST_FRAMEWORK配置,你已经加了JSONRenderer,这没问题,不用改
内容的提问来源于stack exchange,提问作者Diego Jancic
相关产品推荐
相关产品推荐

