Django表单验证失效:form.errors未返回400请求,超长内容未被拦截
问题与解决方案
问题描述
提交表单时,内容超过设置的240字符限制,但表单未触发验证错误,后端也没有返回Bad Request响应,模板中无法显示错误提示。
错误分析与修复步骤
1. 表单验证方法命名错误(forms.py)
Django表单的字段验证方法必须遵循clean_<字段名>的命名规则,且获取验证后的数据需用self.cleaned_data而非拼写错误的self.validated_data。
修正后的forms.py:
from django import forms from .models import Postit MAX_POST_LENGTH = 240 class PostForm(forms.ModelForm): class Meta: model = Postit fields = ['content'] def clean_content(self): content = self.cleaned_data.get("content") if len(content) > MAX_POST_LENGTH: raise forms.ValidationError("这条消息太长了") return content
2. 视图AJAX请求判断逻辑错误(views.py)
原代码中request.headers.get('X-Requested-With' or "HTTP_X_REQUESTED_WITH")的写法存在逻辑漏洞,or运算符优先级导致只会取第一个常量值。需直接检查X-Requested-With请求头是否为XMLHttpRequest。
修正后的post_create_view函数:
def post_create_view(request, *args, **kwargs): form = PostForm(request.POST or None) next_url = request.POST.get('next') or None if form.is_valid(): obj = form.save(commit=False) obj.save() # 正确判断AJAX请求 if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return JsonResponse(obj.serialize(), status=201) if next_url is not None and url_has_allowed_host_and_scheme(next_url, 'localhost'): return redirect(next_url) form = PostForm() # 处理表单错误 if form.errors: if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return JsonResponse(form.errors, status=400) return render(request, 'comp/form.html', context={"form": form})
3. 前端未处理错误响应(模板与JS)
原前端代码仅处理了201成功状态,未处理400错误响应,需添加错误提示区域并完善JS逻辑。
模板中添加错误提示区域:
<form class='form' id='create-post-form' method='POST' action='/create-post'> {% csrf_token %} <input type='hidden' value="/" name="next"/> <textarea required="required" class='form-control' name="content" placeholder="在这里输入消息..."></textarea> <!-- 错误提示区域 --> {% if form.content.errors %} <div class="text-danger mt-2"> {{ form.content.errors.0 }} </div> {% endif %} <button type='submit' class="btn btn-primary mt-2">发布</button> </form>
完善前端JS的错误处理逻辑:
function handleCreatePostFormDidSubmit(event) { event.preventDefault() const myForm = event.target const myFormData = new FormData(myForm) const url = myForm.getAttribute("action") const method = myForm.getAttribute("method") const xhr = new XMLHttpRequest() const responseType = "json" xhr.responseType = responseType xhr.open(method, url) xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest") xhr.onload = function() { // 清除之前的错误提示 const existingError = myForm.querySelector('.text-danger'); if (existingError) existingError.remove(); if (xhr.status === 201) { const newPostJson = xhr.response const newPostElement = formatPostElement(newPostJson) const ogHtml = postElementContainer.innerHTML postElementContainer.innerHTML = newPostElement + ogHtml myForm.reset() } else if (xhr.status === 400) { // 显示后端返回的错误信息 const errors = xhr.response; if (errors.content) { const errorDiv = document.createElement('div'); errorDiv.className = 'text-danger mt-2'; errorDiv.textContent = errors.content[0]; myForm.querySelector('textarea').insertAdjacentElement('afterend', errorDiv); } } } xhr.send(myFormData) }
内容的提问来源于stack exchange,提问作者mpysys
相关产品推荐
相关产品推荐

