You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 23:30:28