Django+AJAX异步上传图片遇问题:请求未识别为AJAX且视图无响应
Django+AJAX图片上传无刷新处理问题
我尝试用Django结合AJAX实现图片上传至服务器处理,完成后无需刷新页面获取响应,但点击提交按钮后出现错误:
The view docs.views.generate didn't return an HttpResponse object. It returned None instead.
排查发现is_ajax值为false,且前端的form_data未添加任何数据。现有疑问:
- Django 3.1+版本中,如何正确判断请求为AJAX请求?
- 有没有简便方法将服务器返回的文本展示在页面指定位置?
现有代码
models.py
class Snip(models.Model): # some fields snip = models.FileField(upload_to="snips/") latex = models.TextField(default = '')
forms.py
from .models import Snip from django import forms class SnipForm(forms.ModelForm): class Meta: model = Snip fields = ['snip']
HTML
<form id="snipForm" method="POST" enctype="multipart/form-data"> <input type="hidden" name="csrfmiddlewaretoken" value="..."> <div class="row align-items-center"> <div class="col-12"> <label for="id_snip">Snip:</label> <input type="file" name="snip" required="" id="id_snip" class="btn-success p-2 rounded"> <input type="submit" name="upload" id="upload" class="btn btn-secondary"> </div> </div> </form>
JavaScript/AJAX
var upload_btn = document.getElementById("upload") upload_btn.addEventListener('click', function () { var form_data = new FormData(); var ins = document.getElementById('id_snip').files.length; if(ins == 0) return console.log("No snip!!!") form_data.append("file[]", snip.files[0]); csrf_token = $('input[name="csrfmiddlewaretoken"]').val(); form_data.append("csrfmiddlewaretoken", csrf_token); headers = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}; console.log(form_data); console.log(headers); $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest'); } }); $.ajax({ type: 'POST', url: 'https://localhost:8000/docs/', dataType: "json", ContentType: "application/json", cache: false, processData: false, headers: headers, data: form_data, success: function (response) { console.log("SUCCESSSSSSSSS") }, error: function (response) { console.log("NOPEEEEEE") } }); });
views.py
from django.shortcuts import render from django.contrib.auth.models import User from .models import Snip from .forms import SnipForm from django.http import JsonResponse from django.core import serializers def generate(request): is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' if is_ajax and request.method == "POST": file = request.FILES['snip'] processed_image = "Some text from OCR" return JsonResponse({'text':'Yay, I got text from OCR'}) if request.method == 'GET': Users = User.objects.all() form = SnipForm() user_list = [] for user in Users: if user.get_full_name(): user_list.append(user.get_full_name()) return render(request, "new.html", {'Users': user_list, 'form': form})
更新内容
尝试添加$.ajaxSetup设置请求头,但Django错误页面仍未找到HTTP_X_REQUESTED_WITH的META信息,且form_data依旧为空,控制台输出:
FormData {} {HTTP_X_REQUESTED_WITH: 'XMLHttpRequest'}
错误问题仍未解决。
解决方案
1. 修复AJAX请求问题(解决is_ajax为false、form_data为空)
- 阻止表单默认提交行为:点击按钮时添加
event.preventDefault(),避免表单默认刷新提交打断AJAX请求:upload_btn.addEventListener('click', function (event) { event.preventDefault(); // 新增这行 // 后续代码不变 }); - 修正文件字段名:后端取
request.FILES['snip'],所以FormData的键名要和表单字段一致,且snip变量未定义,需替换为DOM元素:// 替换原来的form_data.append("file[]", snip.files[0]); var fileInput = document.getElementById('id_snip'); form_data.append("snip", fileInput.files[0]); - 修正AJAX的Content-Type配置:FormData会自动生成正确的Content-Type(带boundary),手动设为json会导致后端无法解析文件,需改为:
$.ajax({ // ...其他配置 contentType: false, // 替换原来的ContentType: "application/json" // ...其他配置 }); - 修正请求头设置:JS中设置请求头时用
X-Requested-With,Django会自动转为HTTP_X_REQUESTED_WITH存入META:$.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); } });
2. 展示处理后的文本
- 在HTML中添加一个结果展示区域:
<!-- 放在form标签下方 --> <div id="ocr-result" class="mt-3"></div> - 在AJAX的success回调中插入响应文本:
success: function (response) { document.getElementById('ocr-result').textContent = response.text; console.log("SUCCESSSSSSSSS") },
3. 完善后端视图(避免返回None)
在视图末尾添加默认返回,处理非AJAX的POST请求:
def generate(request): is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' if is_ajax and request.method == "POST": try: file = request.FILES['snip'] # 替换为你的OCR处理逻辑 processed_text = "Some text from OCR" return JsonResponse({'text': processed_text}) except KeyError: return JsonResponse({'error': '未上传文件'}, status=400) if request.method == 'GET': Users = User.objects.all() form = SnipForm() user_list = [user.get_full_name() for user in Users if user.get_full_name()] return render(request, "new.html", {'Users': user_list, 'form': form}) # 处理非AJAX的POST请求 return render(request, "new.html", {'form': SnipForm(), 'Users': []})
内容的提问来源于stack exchange,提问作者Wincij
相关产品推荐
相关产品推荐

