Django注册页面出现500内部服务器错误,如何修复is_ajax属性问题?
Django注册页面500内部服务器错误:修复is_ajax相关问题
问题描述
注册页面触发500内部服务器错误,排查后锁定views.py中is_ajax属性相关逻辑存在问题,相关代码如下:
views.py
class SignUpView(AjaxFormMixin, FormView): ''' 集成自定义Mixin的通用FormView,用于带reCAPTCHA验证的用户注册 ''' template_name = "users/sign_up.html" form_class = UserForm success_url = "/" # 向上下文传入reCAPTCHA公钥 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["recaptcha_site_key"] = settings.RECAPTCHA_PUBLIC_KEY return context # 重写Mixin逻辑,处理reCAPTCHA验证并保存分数 def form_valid(self, form): response = super(AjaxFormMixin, self).form_valid(form) if self.request.is_ajax(): token = form.cleaned_data.get('token') captcha = reCAPTCHAValidation(token) if captcha["success"]: obj = form.save() obj.email = obj.username obj.save() up = obj.userprofile up.captcha_score = float(captcha["score"]) up.save() login(self.request, obj, backend='django.contrib.auth.backends.ModelBackend') # 设置成功结果和提示信息 result = "Success" message = "Thank you for signing up" data = {'result': result, 'message': message} return JsonResponse(data) return response
urls.py
from django.urls import path from . import views app_name = "users" urlpatterns = [ path('', views.AccountView.as_view(), name="account"), path('profile', views.profile_view, name="profile"), path('sign-up', views.SignUpView.as_view(), name="sign-up"), path('sign-in', views.SignInView.as_view(), name="sign-in"), path('sign-out', views.sign_out, name="sign-out"), ]
sign_up.html及base.html
{% extends 'base.html' %} {% load static %} {% block extend_head %} <script src='https://www.google.com/recaptcha/api.js?render={{recaptcha_site_key}}'></script> {% endblock %} {% block content %} <h3>Django Google API 课程 - 注册</h3> <div class="container"> <form id="signupform" method="POST" action="/sign-up"> {% csrf_token %} <label for="first_name">名字</label> {{form.first_name}} <label for="last_name">姓氏</label> {{form.last_name}} <label for="username">用户名</label> {{form.username}} <label for="password1">密码</label> {{form.password1}} <label for="password2">确认密码</label> {{form.password2}} {{form.token}} <label class="check-container">显示密码 <input type="checkbox" onclick="showPword()"> <span class="checkmark"></span> </label> <button type="submit">注册</button> </form> </div> {% endblock %} {% block extend_footer %} <script type="text/javascript"> // 创建可在main.js中使用的变量 var recaptcha_site_key = '{{recaptcha_site_key|safe}}' </script> {% endblock %} <!-- base.html --> {% load static %} <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="preconnect" href="https://fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet"> <link rel="stylesheet" href="{% static 'main.css' %}"></link> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.css" integrity="sha512-3pIirOrwegjM6erE5gPSwkUzO+3cTjpnV9lexlNZqvupR64iZBnOOTiiLPb9M36zpMScbmUNIcHUqKD47M719g==" crossorigin="anonymous" referrerpolicy="no-referrer" /> {% block extend_head %} {% endblock %} </head> <body> {% include 'partials/nav.html' %} <div class="div-container"> {% include 'partials/logo.html' %} {% block content %} {% endblock %} </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js" integrity="sha512-VEd+nq25CkR676O+pLBnDW09R7VQX9Mdiij052gVCp5yVH3jGtH70Ho/UUv4mJDsEdTvqRCFZg0NKGiojGnUCw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> {% block extend_footer %} {% endblock %} <script src="{% static 'main.js' %}"></script> </body> </html>
修复方案
1. 替换弃用的is_ajax()方法
Django 3.1及以上版本已弃用request.is_ajax(),需手动检查请求头判断是否为AJAX请求:
# 替换原有的if self.request.is_ajax(): if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
2. 修复未定义变量的报错
当前代码中,如果captcha["success"]为False,result和message变量未初始化就被赋值,会直接抛出NameError,这是500错误的核心诱因之一,修改后代码如下:
def form_valid(self, form): response = super(AjaxFormMixin, self).form_valid(form) # 替换is_ajax判断逻辑 if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest': token = form.cleaned_data.get('token') captcha = reCAPTCHAValidation(token) # 初始化默认结果 result = "Error" message = "验证失败,请重试" if captcha["success"]: obj = form.save() obj.email = obj.username obj.save() up = obj.userprofile up.captcha_score = float(captcha["score"]) up.save() login(self.request, obj, backend='django.contrib.auth.backends.ModelBackend') # 设置成功结果和提示信息 result = "Success" message = "感谢注册" data = {'result': result, 'message': message} return JsonResponse(data) return response
3. 确保前端以AJAX方式提交表单
当前HTML表单为普通同步提交,不会触发后端的AJAX逻辑,需在main.js中添加AJAX提交代码:
$(document).ready(function() { $('#signupform').submit(function(e) { e.preventDefault(); // 阻止普通表单提交 const csrfToken = $('input[name="csrfmiddlewaretoken"]').val(); const formData = $(this).serialize(); // 获取reCAPTCHA令牌并发送请求 grecaptcha.ready(function() { grecaptcha.execute(recaptcha_site_key, {action: 'signup'}).then(function(token) { formData += '&token=' + token; $.ajax({ url: '/sign-up', type: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest' // 手动标记AJAX请求 }, data: formData, success: function(response) { response.result === 'Success' ? (toastr.success(response.message), window.location.href='/') : toastr.error(response.message); }, error: function() { toastr.error('服务器错误,请稍后重试'); } }); }); }); }); });
4. 查看详细错误日志
开发环境下开启Django的DEBUG模式,直接查看500错误的完整栈信息,确认是否存在其他潜在问题(比如reCAPTCHAValidation函数报错、userprofile关联对象未创建等)。
内容的提问来源于stack exchange,提问作者mangesh vispute
相关产品推荐
相关产品推荐

