【问题标题】:Ajax POST Form to Django Data IssueAjax POST 表单到 Django 数据问题
【发布时间】:2013-02-25 08:22:37
【问题描述】:

这几天对此感到沮丧,想知道是否有人可以提供帮助。我是 Ajax 的新手,并试图从登录表单中发布数据以登录 Django (Django Userena)。但是,当我尝试发布数据时,alert() 将数据中的错误显示为 [object object]。我什至看不到网络错误代码,因为 POST 在运行之前就被取消了。

有没有办法只发送数据而不是我认为发送的整个 JSON 数组,或者我需要在 Django 视图后端解析它。明智地完成此代码的最佳方法是什么?非常感谢!

下面是相关代码:

Ajax 代码:

$('#login').submit(function(){

    $.ajax({

        url: 'http://127.0.0.1:8000/accounts/signin/',
        type: 'POST',
        data: {
            csrfmiddlewaretoken: '{{csrf_token}}',
            identification: $("#id_identification").val(),
            password: $("#id_password").val(),
            },
        success: function() {
            alert('Test');
            $('#datadisplay').append("<h2>It worked</h2>");
        },  
        error: function(errorThrown){
            console.log(errorThrown);
            alert('Error');
            alert(errorThrown);
        }
    });
});

Index.html 上的表单

<form name="login" id="login" action="">
   <fieldset>
           <label for="id_identification">Email or username</label>
           <input class="required" id="id_identification" maxlength="75" name="identification" type="text" />

           <label for="id_password">Password</label>
           <input class="required" id="id_password" name="password" type="password" />

           <input type="submit" name="submit" class="loginbutton" value="Login" />
       </fieldset>
   </form>

来自 Django-Userena 的views.py

@secure_required
def signin(request, auth_form=AuthenticationForm,
           template_name='userena/signin_form.html',
           redirect_field_name=REDIRECT_FIELD_NAME,
           redirect_signin_function=signin_redirect, extra_context=None):
    """
    Signin using email or username with password.

    Signs a user in by combining email/username with password. If the
    combination is correct and the user :func:`is_active` the
    :func:`redirect_signin_function` is called with the arguments
    ``REDIRECT_FIELD_NAME`` and an instance of the :class:`User` who is is
    trying the login. The returned value of the function will be the URL that
    is redirected to.

    A user can also select to be remembered for ``USERENA_REMEMBER_DAYS``.

    :param auth_form:
        Form to use for signing the user in. Defaults to the
        :class:`AuthenticationForm` supplied by userena.

    :param template_name:
        String defining the name of the template to use. Defaults to
        ``userena/signin_form.html``.

    :param redirect_field_name:
        Form field name which contains the value for a redirect to the
        succeeding page. Defaults to ``next`` and is set in
        ``REDIRECT_FIELD_NAME`` setting.

    :param redirect_signin_function:
        Function which handles the redirect. This functions gets the value of
        ``REDIRECT_FIELD_NAME`` and the :class:`User` who has logged in. It
        must return a string which specifies the URI to redirect to.

    :param extra_context:
        A dictionary containing extra variables that should be passed to the
        rendered template. The ``form`` key is always the ``auth_form``.

    **Context**

    ``form``
        Form used for authentication supplied by ``auth_form``.

    """
    form = auth_form()

    if request.method == 'POST':
        form = auth_form(request.POST, request.FILES)
        if form.is_valid():
            #identification, password, remember_me = (form.cleaned_data['identification'],
                                                     #form.cleaned_data['password'],
                                                    #form.cleaned_data['remember_me'])
            identification, password = (form.cleaned_data['identification'], form.cleaned_data['password'])     

            user = authenticate(identification=identification,
                                password=password)
            if user.is_active:
                login(request, user)
                if remember_me:
                    request.session.set_expiry(userena_settings.USERENA_REMEMBER_ME_DAYS[1] * 86400)
                else: request.session.set_expiry(0)

                if userena_settings.USERENA_USE_MESSAGES:
                    messages.success(request, _('You have been signed in.'),
                                     fail_silently=True)

                # Whereto now?
                redirect_to = redirect_signin_function(
                    request.REQUEST.get(redirect_field_name), user)
                return HttpResponseRedirect(redirect_to)
            else:
                return redirect(reverse('userena_disabled',
                                        kwargs={'username': user.username}))

    if not extra_context: extra_context = dict()
    extra_context.update({
        'form': form,
        'next': request.REQUEST.get(redirect_field_name),
    })
    return ExtraContextTemplateView.as_view(template_name=template_name,
                                            extra_context=extra_context)(request)

身份验证表单

class AuthenticationForm(forms.Form):
    """
    A custom form where the identification can be a e-mail address or username.

    """
    identification = identification_field_factory(_(u"Email or username"),
                                                  _(u"Either supply us with your email or username."))
    password = forms.CharField(label=_("Password"),
                               widget=forms.PasswordInput(attrs=attrs_dict, render_value=False))
    remember_me = forms.BooleanField(widget=forms.CheckboxInput(),
                                     required=False,
                                     label=_(u'Remember me for %(days)s') % {'days': _(userena_settings.USERENA_REMEMBER_ME_DAYS[0])})

    def __init__(self, *args, **kwargs):
        """ A custom init because we need to change the label if no usernames is used """
        super(AuthenticationForm, self).__init__(*args, **kwargs)
        # Dirty hack, somehow the label doesn't get translated without declaring
        # it again here.
        self.fields['remember_me'].label = _(u'Remember me for %(days)s') % {'days': _(userena_settings.USERENA_REMEMBER_ME_DAYS[0])}
        if userena_settings.USERENA_WITHOUT_USERNAMES:
            self.fields['identification'] = identification_field_factory(_(u"Email"),
                                                                         _(u"Please supply your email."))

    def clean(self):
        """
        Checks for the identification and password.

        If the combination can't be found will raise an invalid sign in error.

        """
        identification = self.cleaned_data.get('identification')
        password = self.cleaned_data.get('password')

        if identification and password:
            user = authenticate(identification=identification, password=password)
            if user is None:
                raise forms.ValidationError(_(u"Please enter a correct username or email and password. Note that both fields are case-sensitive."))
        return self.cleaned_data

【问题讨论】:

  • 我没有看到任何易受 POST JSON 数组影响的代码。 AJAX 请求的响应代码是什么?也许{{ csrf_token }} 是空的?
  • 您可以尝试使用@csrf_exempt 暂时删除 csrf 验证,看看其他地方是否也存在其他问题
  • 感谢您的回复。我无法获得响应代码,因为它在完成之前错误退出。上面代码中的控制台打印“Object {readyState: 0, getResponseHeader: function, getAllResponseHeaders: function, set RequestHeader: function, overrideMimeType: function...}”但是一旦我关闭最后一个对话框,它就会退出并清除控制台。当表单不是通过 Django 而是通过外部 html 表单显示时,我将如何在表单中放入 csrf_token?
  • 啊,我多么愚蠢!这可能是问题所在,如果我需要,您是否知道如何在我的 index.html 页面上引用表单,因为它在 Django View 之外?感谢您迄今为止的帮助!

标签: ajax django forms post login


【解决方案1】:

这些是我在测试您的代码时看到的错误(不是全部,我认为还有更多):

  1. 如果您没有在模板中使用 AuthenticationForm(),您将如何登录。您在模板中的表单代码不同。
  2. 您没有将 method="POST" 放入表单中,这会导致 GET 响应而不是 POST。
  3. 您忘记将 {% csrf_token %} 放入模板表单中
  4. 在您的 views.py 中,user = authenticate(identification=identification, password=password) 必须是 user = authenticate(username=identification, password=password)
  5. 在您的 forms.py 中,user = authenticate(identification=identification, password=password) 必须是 user = authenticate(username=identification, password=password)
  6. 您的 ajax 代码没有任何效果,这就是您无法得到错误抛出的原因。我认为您在 ajax 中遗漏了一些东西。
  7. 获取所抛出错误的详细信息:

    error: function(ts){
        //console.log(errorThrown);
        //alert('Error');
        alert(ts.responseText);
        }
    
  8. 你的 ajax 数据必须有 '':

    data: {
        'csrfmiddlewaretoken': '{{csrf_token}}',
        'identification': $("#id_identification").val(),
        'password': $("#id_password").val(),
        },
    
  9. 您不必像这样详细说明您的网址

    url: 'http://127.0.0.1:8000/accounts/signin/',
    

    这会导致

    "http://127.0.0.1:8000/http://127.0.0.1:8000/accounts/signin/"
    

    应该是

    url: '/accounts/signin/',
    

    别忘了放

    contentType: "application/json;charset=utf-8",
    dataType: "json",
    

还有更多错误,直到现在我都无法成功登录。

【讨论】:

  • 感谢您迄今为止的所有帮助。我正在处理这个问题,它现在可以毫无错误地发布,但我认为它没有做任何事情,并且页面只是在没有发送数据的情况下引用。我的目标是制作一个以 Django 为后端的移动应用程序。使用PhoneGap,前端需要是HTML/CSS/JS only,所以没有Django 模板和Django 标签也没有意义。你知道我的让用户登录/注册的目标是否有更简单的解决方案?我认为 TastyPie 可能是前进的方向,但我尝试过,也无法弄清楚。任何见解都会非常有帮助。谢谢!
  • 我对手机一无所知。我也从不使用 TastyPie。如果我能得到一个信息,我会马上告诉你:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多