Django Ajax POST请求出现CSRF Token缺失或错误如何解决?
问题描述
我正在基于Django框架开发Web应用,尝试集成Ajax功能时遇到了简单Ajax调用无法正常运行的问题。
我的需求是:用户在表单中输入数据库凭据后,调用API建立数据库连接,最终返回连接成功或失败的结果。
相关代码
views.py 接口代码
class TestConnectionAPI(views.APIView): ''' Test DB Connection from TARGET DB ''' def post(self, request): dbs = (request.data['host'], request.data['port'], request.data['dbname'], request.data['user'], request.data['password'], request.data['schema_name']) try: x = dc.DbConnection(*dbs) x.create_conn() data = x.check_conn() result = { 'message' : 'Success', 'server' : f'Connection established from {data}', 'results':{ 'host':dbs[0], 'port':dbs[1], 'dbname':dbs[2] }, } return Response(result, status=status.HTTP_200_OK) except Exception as e: return Response({'Message':str(e)}, status=status.HTTP_400_BAD_REQUEST)
前端表单代码(connection.html)
<form method="post"> <div class="modal-body"> <div class="form-group"> <label for="host">Hostname</label> <input type="text" class="form-control" id="host" name="host" aria-describedby="host"> </div> <div class="form-group"> <label for="port">Port</label> <input type="number" class="form-control" id="port" name="port" placeholder="e.g., 5432"> </div> <div class="form-group"> <label for="database">Database name</label> <input type="text" class="form-control" id="dbname" name="dbname" placeholder="Enter database name"> </div> <div class="form-group"> <label for="username">Username</label> <input type="text" class="form-control" id="user" name="user" placeholder="Enter username"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password"> </div> <div class="form-group"> <label for="schema">Schema</label> <input type="text" class="form-control" id="schema_name" name="schema_name"> </div> </div> <div class="modal-footer border-top-0 d-flex justify-content-center"> <a href="#form2" class="btn btn-primary" data-toggle="modal" type="submit" id="btnSubmit">Test</a> <button type="submit" class="btn btn-success">Save</button> </div> </form>
Ajax 请求代码
$('#btnSubmit').click(function () { let _host = $('#host').val(); let _port = $('#port').val(); let _dbname = $('#dbname').val(); let _user = $('#user').val(); let _password = $('#password').val(); let _schema_name = $('#schema_name').val(); var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value'); $.ajax({ type: 'POST', dataType: 'JSON', headers:{"X-CSRFToken": $crf_token}, data:{ "host" : _host, "port" : _port, "dbname" : _dbname, "user" : _user, "password" : _password, "schema_name": _schema_name, }, url:"http://127.0.0.1:8000/api/v1/test/", error: function (xhr, status, error) { var err_msg = '' for (var prop in xhr.responseJSON) { err_msg += prop + ': ' + xhr.responseJSON[prop] + '\n'; } alert(err_msg); }, success: function (result) { console.log(result); } }); });
问题现象
- 报错与CSRF Token相关,请求无法正常触发接口返回结果
- 预期接口成功响应格式如下:
{ "message": "Success", "server": "Connection established from ('PostgreSQL 12.7, compiled by Visual C++ build 1914, 64-bit',)", "results": { "host": "localhost", "port": 5432, "dbname": "dvdrental" } }
解决方案
按以下步骤逐一修复即可:
- 补全表单CSRF标签:在
<form method="post">下第一行添加Django模板标签{% csrf_token %},确保页面渲染后生成name为csrfmiddlewaretoken的隐藏输入框 - 修正CSRF Token取值逻辑:将JS中获取token的代码替换为
var $crf_token = $('input[name="csrfmiddlewaretoken"]').val();
- 阻止a标签默认跳转行为:绑定点击事件的元素是a标签,默认跳转行为会中断Ajax请求,修改点击事件开头新增阻止逻辑
$('#btnSubmit').click(function (e) { e.preventDefault(); // 新增这行 // 原有逻辑保持不变 });
- 确认当前页面域名和Ajax请求的域名一致,避免跨域导致CSRF校验失败
修复完成后重新测试,成功响应会直接打印在浏览器控制台,可按需添加逻辑将结果渲染到页面。
内容的提问来源于stack exchange,提问作者fritzp
相关产品推荐
相关产品推荐

