Django登录注册报错:'WSGIRequest'对象无'is_ajax'属性求解决
问题:登录/注册触发 AttributeError: 'WSGIRequest' object has no attribute 'is_ajax'
报错场景
访问 /sign-up 或 /sign-in 页面时出现以下错误:
AttributeError at /sign-up
'WSGIRequest' object has no attribute 'is_ajax'
原因是Django 3.1及以上版本弃用了request.is_ajax()方法,而代码中多处依赖该方法判断AJAX请求,导致报错。
修复方案
原is_ajax()方法的核心逻辑是检查请求头中是否包含X-Requested-With: XMLHttpRequest,直接手动实现这个判断来替换所有request.is_ajax()调用即可。
1. 修改 mixins.py
class AjaxFormMixin(object): ''' Mixin to ajaxify django form - can be over written in view by calling form_valid method ''' def form_invalid(self, form): response = super(AjaxFormMixin, self).form_invalid(form) # 替换原is_ajax()判断 if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest': message = FormErrors(form) return JsonResponse({'result': 'Error', 'message': message}) return response def form_valid(self, form): response = super(AjaxFormMixin, self).form_valid(form) if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest': form.save() return JsonResponse({'result': 'Success', 'message': ""}) return response
2. 修改 views.py 中的 profile_view 函数
def profile_view(request): ''' function view to allow users to update their profile ''' user = request.user up = user.userprofile form = UserProfileForm(instance=up) # 替换原is_ajax()判断 if request.headers.get('X-Requested-With') == 'XMLHttpRequest': form = UserProfileForm(data=request.POST, instance=up) if form.is_valid(): obj = form.save() obj.has_profile = True obj.save() result = "Success" message = "Your profile has been updated" else: message = FormErrors(form) data = {'result': result, 'message': message} return JsonResponse(data) else: context = {'form': form} context['google_api_key'] = settings.GOOGLE_API_KEY context['base_country'] = settings.BASE_COUNTRY return render(request, 'users/profile.html', context)
3. 修改 views.py 中的 SignUpView 类
class SignUpView(AjaxFormMixin, FormView): ''' Generic FormView with our mixin for user sign-up with reCAPTURE security ''' template_name = "users/sign_up.html" form_class = UserForm success_url = "/" # reCAPTURE key required in context def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["recaptcha_site_key"] = settings.RECAPTCHA_PUBLIC_KEY return context # over write the mixin logic to get, check and save reCAPTURE score 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) 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') # change result & message on success result = "Success" message = "Thank you for signing up" data = {'result': result, 'message': message} return JsonResponse(data) return response
4. 修改 views.py 中的 SignInView 类
class SignInView(AjaxFormMixin, FormView): ''' Generic FormView with our mixin for user sign-in ''' template_name = "users/sign_in.html" form_class = AuthForm success_url = "/" def form_valid(self, form): response = super(AjaxFormMixin, self).form_valid(form) # 替换原is_ajax()判断 if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest': username = form.cleaned_data.get('username') password = form.cleaned_data.get('password') # attempt to authenticate user user = authenticate( self.request, username=username, password=password) if user is not None: login(self.request, user, backend='django.contrib.auth.backends.ModelBackend') result = "Success" message = 'You are now logged in' else: message = FormErrors(form) data = {'result': result, 'message': message} return JsonResponse(data) return response
额外验证
确保前端发送AJAX请求时携带X-Requested-With: XMLHttpRequest请求头:
- 使用jQuery时该头会自动添加;
- 原生JS/fetch需手动设置:
fetch('/sign-up', { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded' }, body: new FormData(document.getElementById('signup-form')) });
内容的提问来源于stack exchange,提问作者Daniel A
相关产品推荐
相关产品推荐

