使用 Ajax jQuery 提交 Django 表单的简单方法

Posted

技术标签:

【中文标题】使用 Ajax jQuery 提交 Django 表单的简单方法【英文标题】:An Easy way to submit Django Forms using Ajax jQuery 【发布时间】:2012-12-15 11:05:02 【问题描述】:

我对 Ajax 比较陌生,我仍在努力掌握所有概念。我尝试查看一堆关于 Ajax-Django 表单提交的教程,其中大多数都需要 jQuery 表单,这对我来说似乎不是一种简单的处理表单提交的方法。我很难理解这个概念。

我正在尝试为用户注册、登录、帖子创建和 cmets 编写一些基于 ajax 的表单提交。到目前为止,我还没有找到一种方法让我更容易理解 Ajax 方法的工作原理。

我非常感谢在这方面能得到的任何帮助。

这是我迄今为止尝试过的。

change_pw.html

% extends "base.html" %
    % block title %Change Password% endblock %
    % block head %Change Password% endblock %
    % block content %
    % include "modal_change_pw.html" %
    % endblock %

modal_change_pw.html

<div id="modalchangepw">
<ul style="margin:5px;">
    <ul class="thumbnails" style="margin: 0 auto;background: white;">
        <div class="thumbnail row-fluid" style="background: white; padding: 10px;width: 97%; -moz-border-radius: 5px;border-radius: 5px;-moz-box-shadow:3px 3px 5px 0px #ccc;-webkit-box-shadow:3px 3px 5px 0px #ccc;box-shadow:3px 3px 5px 0px #ccc;">
            <br>
            % if not error == '' %
                <div class="alert alert-error">
                    <button type="button" class="close" data-dismiss="alert">&times;</button>
                     error 
                </div>
            % endif %
            % if not success == '' %
                <div class="alert alert-success">
                    <button type="button" class="close" data-dismiss="alert">&times;</button>
                     success 
                </div>
            % endif %
            % if messages %
                % for message in messages %
                  <div% if message.tags % class="alert alert- message.tags "% endif %>
                    <button type="button" class="close" data-dismiss="alert">&times;</button>
                     message|safe 
                  </div>
                % endfor %
            % endif %
            <form id = 'changepw' enctype="multipart/form-data" method="post" action=".">
                <p><label for="id_currentpw">Current Password:</label> <input type="password" name="currentpw" id="id_currentpw" /></p>
                <p><label for="id_newpw1">New Password:</label> <input type="password" name="newpw1" id="id_newpw1" /></p>
                <p><label for="id_newpw2">Re-enter New Password:</label> <input type="password" name="newpw2" id="id_newpw2" /></p>
                <input class="btn btn-primary" type="submit" value="submit"/>
                % csrf_token %
            </form>
        </div>
    </ul>
</ul>
</div>

views.py

def change_pw(request):
    user=request.user
    error=''
    success=''
    if request.method == 'POST':
        form = ChangePw(request.POST)
        if form.is_valid():
            currentpw=form.cleaned_data['currentpw']
            newpw1=form.cleaned_data['newpw1']
            newpw2=form.cleaned_data['newpw2']
            if currentpw and newpw1 and newpw2:
                if user.check_password(currentpw):
                    if newpw1==newpw2:
                        user.set_password(newpw1)
                        user.save()
                        success='Password updated!!'
                        if request.is_ajax() :
                            messages.success(request, 'Password updated.')
                            return HttpResponseRedirect ('/changepw/')
                        else:
                            return HttpResponseRedirect ('/user/%s/' % user.username)
                    else:
                        error='New passwords do not match'
                else:
                    error='Incorrect Current Password'
            else:
                error='Enter all Password fields to make any changes' 
    else:
        form = ChangePw()
    variables = RequestContext(request, 
           'form':form,
           'error':error,
           'success':success
    )
    if request.is_ajax() :
         return render_to_response('modal_change_pw.html', variables)
    else:    
        return render_to_response('change_pw.html', variables)

forms.py

class ChangePw(forms.Form):
     currentpw = forms.CharField(
        label=u'Current Password',
        required=False,
        widget=forms.PasswordInput()
     )
     newpw1 = forms.CharField(
        label=u'New Password',
        required=False,
        widget=forms.PasswordInput()
     )
     newpw2 = forms.CharField(
        label=u'Re-enter New Password',
        required=False,
        widget=forms.PasswordInput()
     )

jQuery

//Change PW
        $('#changepw').live('submit', function(event)  // catch the form's submit event
          event.preventDefault();
          $.ajax( // create an AJAX call...
              data: $(this).serialize(), // get the form data
              type: $(this).attr('method'), // GET or POST
              url: $(this).attr('action'), // the file to call
              success: function(response)  // on success..
                  $('#modalchangepw').html(response); // update the DIV
              
          );
          return false;
        );

代码现在似乎工作正常。 但我的目标是以模态弹出方式处理这些表单,这样用户就不必离开他/她当前所在的页面。在模态弹出窗口的情况下,我的表单似乎没有提交值。

【问题讨论】:

whathaveyoutried.com ? - 请提供一些您尝试过但无法开始工作的相关代码。 :) 很抱歉没有早点添加代码。我没有任何 jQuery 代码,因为我很难理解这个概念。根据我确实尝试添加 AJAX 逻辑的答案,但它似乎不起作用 【参考方案1】:

AJAX 概念与一般表单提交的工作方式没有太大区别。 AJAX 背后的想法是异步提交(传递)数据到服务器。

它是如何工作的?

一般的表单提交流程是这样的。

User submits a POST request
               ↓
Server Does the Data Processing
               ↓
Redirects to a Success or Failure Page

使用 ajax 的工作方式非常相似。

User Submits a form through AJAX
               ↓
AJAX sends the POST data to the server in the background and waits for a response
               ↓
Server does the Data Processing
               ↓
and sends a Response back to AJAX
               ↓
AJAX sends the response back to the same template where the request was initiated.

现在让我们看看一个简单的带有 django 视图的 Ajax 登录。

views.py

def ajax_login(request):
    """  
    This view logs a user in using the POST data.
    """

    if request.method == 'POST':
        data = 
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if (not user is None) and (user.is_active):
            login(request, user)
            # Set Session Expiry to 0 if user clicks "Remember Me"
            if not request.POST.get('rem', None):
                request.session.set_expiry(0)
            data['success'] = "You have been successfully Logged In"
        else:
            data['error'] = "There was an error logging you in. Please Try again"
        return HttpResponse(simplejson.dumps(data), mimetype="application/json")

在上面的视图中,我们进行了数据处理并返回了一个 JSON 响应。 ajax 方法看起来像这样。

function ajaxLogin()
    var dataString = '&username=' + $('input[name=username]').val() +
                     '&password=' + $('input[name=password]').val() +
    $.ajax(
        type: "POST",
        url: "/ajax_login/",
        data: dataString,
        success: function(data) 
            alert(data);
           
     ); 
     return false;   

在这里,success 方法将数据返回并alerts 发送给用户。

更新

我看到您已经定义了 ajaxPwchange() 方法,但我并没有真正看到您在任何地方调用它,我认为这就是页面仍然刷新的原因。您可以绑定ajaxPwchange()方法来提交按钮的onclick事件,如下所示。

<input class="btn btn-primary" type="submit" value="submit" onclick="ajaxPwchange();" />

或者在document.ready方法下绑定如下:

$(document).ready(function()
    $('input.btn-primary').click(function()
        ajaxPwchange();
    );
);

更新2

div 消失了,因为您在以下代码中直接将 div 的 html 更改为 json 对象。

success: function(response)  // on success..
             $('#modalchangepw').html(response); // update the DIV
         

你应该尝试这样的事情:

success: function(response)  // on success..
             var jsonData = $.parseJSON(response);
             $.each(response, function()
                 $('#modalchangepw').append('<div class="message">' + $(this) + '</div>');
             );
         

【讨论】:

我喜欢向下的箭头和解释。 很抱歉没有早点添加代码。我没有任何 jQuery 代码,因为我很难理解这个概念。根据我确实尝试添加 AJAX 逻辑的答案,但它似乎不起作用 @Amyth 谢谢你的回复。即使是 onclick 和文档就绪方法也不起作用。我已将代码更新为似乎可以工作的内容,请看一下 嘿@Jonathan,我添加了另一个更新。请看一看。 @Amyth 非常感谢!这是一个愚蠢的错误。现在它工作得很好!非常感谢!【参考方案2】:

我会给你一个非常简单的例子,这样你就可以掌握这个概念,然后使用相同的概念来做你想做的事情。

我将首先在views.py 中创建一个普通视图

def MyAjaxView(request):
    if request.is_ajax():
         if request.method == 'GET':
             # If it was a GET
             print request.GET
         elif request.method == 'POST':
             # Here we can access the POST data
             print request.POST
    else:
         doSomeOtherStuff()
    return render_to_response('mytemplate.html', some_context_maybe, context_instance=RequestContext(request))

根据您已经使用的内容或允许使用的内容,您可以使用 javascript 或库 jQuery 来调用它。

假设你有一个看起来像这样的表单

<form id="myNameForm">
   % csrf_token %
   <input type="text" id="name" />
   <input type="submit" value="submit" id="submitButton" />
</form>

您现在可以使用 JavaScript 将其连接到一个 ajax 函数,我将使用 jQuery 作为演示,我将使用 jQuery 方法 ajax() 因为它解释了这个概念,然后转到 post() 不应该太难了。

<script>
    $('#submitButton').click(function(event)
         event.preventDefault(); //so that we stop normal form submit.
         $.ajax(
             url: 'myViewUrl',
             type: 'post',
             dataType: 'json',
             data: $('form#myNameForm').serialize(),
             success: function(data) 
               doStuffWithDataHere(data);
             
         );
    );
</script>

您必须确保您的 urls.py 具有到新视图的 url 映射。 使用 CSRF 保护还需要使用 CSRF 处理器,请参阅 BurhanKhalids 注释以获取文档。

【讨论】:

if 条件周围不需要额外的()。使用render 自动传入RequestContext。请记住,您必须从视图中返回 HttpResponse。简单地打印东西会导致错误。最后,您需要使用csrf protection 进行 POST 请求。 绝对! :) 谢谢@BurhanKhalid 我只是在编写一些java代码,parens开始标记! :) 很抱歉,也感谢 csrf_token,我忘记了。 @BurhanKhalid - 请澄清一下。我是否可以将 ajax 请求发送到不同于最初用于呈现 formview 请求?到POST 表单数据。 当然可以。您可以将请求发送到任何视图。 @BurhanKhalid - 实际上我做不到。我尝试了各种方法来编写 FBV 来做到这一点,但遗憾的是,似乎没有一个方法可以发布数据。在 console 中,我可以看到很好地序列化了表单数据,但它没有发布到数据库中。您能否指出一个最小的示例,说明 view 对于management_formparent/child)场景应该是什么样子的? PS - 直到我从你那里得知,我几乎开始相信将 ajax 请求发送到不同的 viewPOST 是不可能的!!跨度>

以上是关于使用 Ajax jQuery 提交 Django 表单的简单方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 django ajax jquery 提交一个文件不起作用的表单

Ajax jQuery serialize() & serializeArray() textarea 未以 Django 形式提交

python测试开发django-131.jQuery中$.ajax()方法POST提交contentType:“application/json“类型数据

如何在 Django 模板中使用 Jquery/Ajax 正确刷新 div

Django Ajax ModelForm 向 request.POST 提交一个空表单

jquery ajax 提交form表单 以及django后台接受