首页 > 解决方案 > Django - 如何在身份验证期间返回 JSON 响应而不是 HTML?

问题描述

我正在构建一个使用标准 Django 会话身份验证的 Vue SPA,因为 Django 应用程序和 Vue 应用程序将位于同一服务器和同一域上。

我一直将django-allauth用于与身份验证相关的所有内容,但在这种情况下,问题是身份验证不是由 Django 模板处理的,而是我使用 AJAX 向 Django 发送 POST 请求以进行注册、登录和所有操作别的。

有没有办法让 Django-Allauth 或 Django 发送 JSON 响应而不是标准 HTML 和重定向?

这是我用来登录的代码中的示例 POST 请求:

bodyFormData.append('csrfmiddlewaretoken', this.csrf_token)
bodyFormData.append('login', 'root');
bodyFormData.append('password', 'Stest');

axios({
  method: "post",
  url: "http://127.0.0.1:8000/accounts/login/",
  data: bodyFormData,
  withCredentials: true,
  headers: {"Content-Type": "application/json"},
})
.then(function (response) {
  //handle success
})
.catch(function (response) {
  //handle error
});

是登录视图:

class LoginView(
    RedirectAuthenticatedUserMixin, AjaxCapableProcessFormViewMixin, FormView
):
    form_class = LoginForm
    template_name = "account/login." + app_settings.TEMPLATE_EXTENSION
    success_url = None
    redirect_field_name = "next"

    @sensitive_post_parameters_m
    def dispatch(self, request, *args, **kwargs):
        return super(LoginView, self).dispatch(request, *args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super(LoginView, self).get_form_kwargs()
        kwargs["request"] = self.request
        return kwargs

    def get_form_class(self):
        return get_form_class(app_settings.FORMS, "login", self.form_class)

    def form_valid(self, form):
        success_url = self.get_success_url()
        try:
            return form.login(self.request, redirect_url=success_url)
        except ImmediateHttpResponse as e:
            return e.response

    def get_success_url(self):
        # Explicitly passed ?next= URL takes precedence
        ret = (
            get_next_redirect_url(self.request, self.redirect_field_name)
            or self.success_url
        )
        return ret

    def get_context_data(self, **kwargs):
        ret = super(LoginView, self).get_context_data(**kwargs)
        signup_url = passthrough_next_redirect_url(
            self.request, reverse("account_signup"), self.redirect_field_name
        )
        redirect_field_value = get_request_param(self.request, self.redirect_field_name)
        site = get_current_site(self.request)

        ret.update(
            {
                "signup_url": signup_url,
                "site": site,
                "redirect_field_name": self.redirect_field_name,
                "redirect_field_value": redirect_field_value,
            }
        )
        return ret

这似乎工作正常,它让我登录,但响应是 HTML 并且从网络选项卡中我可以看到 Django 尝试将我重定向到另一个页面(因为这就是它在 Django 模板处理身份验证时所做的事情)。

有什么办法可以让它只发送 JSON 响应?我必须覆盖某些视图还是被迫更改库的代码?任何建议表示赞赏

标签: pythondjangoajax

解决方案


我简要浏览了 django-allauth 的代码。我看到了一个可能使您朝着正确方向前进的机会?

django-allauth 允许您设置自己的适配器。

例如,如果您有一个名为“my_applabel”的应用程序,并使用以下类放置一个文件 custom_adapter.py 并继承DefaultAccountAdapter

class MyOwnAdapter(DefaultAccountAdapter):
    def ajax_response(self, request, response, redirect_to=None, form=None, data=None):
        # Craft your own response.

在设置中尝试 ACCOUNT_ADAPTER = 'my_applabel.custom_adapter.MyOwnAdapter'

请参阅文档ACCOUNT_ADAPTER

它提供了从 DefaultAccountAdapter 覆盖某些行为/方法的机会。


推荐阅读