使用 bootstrap 和 django 的异步表单

Posted

技术标签:

【中文标题】使用 bootstrap 和 django 的异步表单【英文标题】:Asynchronous forms with bootstrap and django 【发布时间】:2012-10-05 23:03:40 【问题描述】:

所以我试图使这种形式异步。理想情况下,我使用此表单添加单位,然后动态更新表格。我不希望整个页面刷新。我不太擅长 javascript,我可以使用一些指针来了解正在发生的事情:

发生了一些我不想发生的事情:

    整个页面都在刷新 request.is_ajax() 为 False。

大多数情况下,我只是想了解发生了什么,但问题是,如何更改以下内容以解决上述两个问题? (如果它们是问题,那就是问题。)

以下部分代码取自这个问题:

How do I insert a django form in twitter bootstrap modal window?

作为记录,我在 request.POST 中看到帖子很好,我只是想让它异步工作,这就是我的问题与上述问题的不同之处。

% block scripts %
<script type="text/javascript">
    $(document).ready(function() 
        modalConnect();
    );
</script>

<script type="text/javascript">
$( document ).ajaxStop( function() 
    modalConnect();
);
</script>

<script type="text/javascript">
    function modalConnect()
        
            //unbind the click event. If not done we will end up with multiple click event bindings, since binding is done after each ajax call.
            $(".editItem").unbind('click');
            //bind the click event
            $(".editItem").click(function(ev)  // for each edit item <a>
                ev.preventDefault(); // prevent navigation
                var url = this.href; //get the href from the <a> element
                $.get(url, function(results)
                  //get the form
                  var itemForm = $("#ajax_form_modal_result", results);
                  //get the update URL
                  var formUpdateURLDiv = $("#formUpdateURL", results);
                  //get the inner html of the div
                  var formUpdateURL = formUpdateURLDiv.html();
                  //update the dom with the received form
                  $('#inventory').html(itemForm);
                  //show the bootstrap modal
                  $("#inventory").modal('show');
                  $(document).ready(function () 
                     //bind the form to an ajax call. ajax call will be set to the received update url
                     submitItemModalFormBind(formUpdateURL);
                  );
                , "html");
                return false; // prevent the click propagation
            )
        
</script>

<script type="text/javascript">
       function submitItemModalFormBind(url)
         //bind the form. prevent default behavior and submit form via ajax instead
         $('#ajax_form_modal_result').submit(function(ev)
             $.ajax(
                type: "POST",
                url: url,
                data: $(this).serialize(),
                success:function(response, textStatus, jqXHR)
                     var form = $("#ajax_form_modal_result_div", response);
                     //form is returned if it is not valid. update modal with returned form
                     //change this "if" to check for a specific return code which should be set in the view
                     if (form.html()) 
                        console.log('Form was invalid and was returned');
                        //update modal div
                         $('#ajax_form_modal_result_div').html(form);
                         $("#inventory").modal('show');
                      
                      //form is not returned if form submission succeeded
                      else
                        //update the entire document with the response received since we received a entire success page and we want to reload the entire page

                        //sort by modified date descending

                        //var notificationDiv = $("#notification", response);
                        //$('#notification').html(notificationDiv.html());
                        console.log('Form was valid and was not returned');
                        $("#inventory").modal('hide');
                        
                ,
                error: function (request, status, error) 
                            var div = $("ajax_form_modal_result_div", request.responseText);
                            $('#ajax_form_modal_result_div').html(div);
                            //implement proper error handling
                            console.log("failure");
                            console.log(request.responseText);
                        
                    );
                    return false;
                );
              
</script>



% endblock %

% block content %

<div class="row">
    <div class="span8 offset4">
        <div class="row">
            <div class="span3">
                <h1>
                Acquisitions
                </h1>
            </div>
            <div class="span3 offset2">
                <h1>
                <a id="editItem" href="#inventory" role="button" class="icon-plus-sign" data-toggle="modal"></a>
                Add Units
                </h1>
            </div>
        </div>
        <table class="table table-hover table-striped">
            <thead>
                <tr>
                    <th>
                    lolcats
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>
                    lolcats
                    </td>
                </tr>
                    <tr>
                    <td>
                    test
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>


    <div class="modal hide fade" id="inventory" >
<form id="#ajax_form_modal_result" class="well" method="post" action="">
 <div id="ajax_form_modal_result_div">


    <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
    <h3>Add units</h3>
    </div>
    <div class="modal-body">
        % csrf_token %
         inventory.as_p

    </div>
    <div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <input class="btn btn-primary" type="submit" value="Save" />

    </div>

   </div>
</form>
</div>

【问题讨论】:

【参考方案1】:

由于缺乏 JS 经验,当我开始使用 Django 时,我在 AJAX 上苦苦挣扎。

我会给你一个我用来添加选项和显示选项的 aync 表单的例子。

我的模板模态代码如下,它可以与正在呈现的表单而不是我的懒惰硬编码 html 一起工作。

   <div class="modal" id="AddOptions" style="display:none;">
  <div class="modal-header">
    <button class="close" data-dismiss="modal">X</button>
    <h3>Add Options</h3>
  </div>
  <div class="modal-body">

<form id="OptionForm" action="." method='POST'>
  <div id="OptionValueError" class="control-group">
  <span class="help-inline"></span><br>
  <br>Value&nbsp;<input type="text" name="OptionValue" id="id_OptionValue" /><br>Label&nbsp;<input type="text" name="OptionLabel" id="id_OptionLabel"/><input type="hidden" name="VariableID">
  </div>
<div id="divid_OptionTable">
<table class="table table-condensed" id="OptionTable">
<thead>
  <th>Value</th>
  <th colspan="2">Label</th>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
  <div class="modal-footer">
  <input type="submit" class="btn btn-primary" value="Add">&nbsp;<button type="reset" class="btn">Reset</button>
</form>
  </div>
</div>

接下来,请确保您有以下内容来处理 CSRF 令牌问题。

<script type="text/javascript"> 
jQuery(document).ajaxSend(function(event, xhr, settings) 
    function getCookie(name) 
        var cookieValue = null;
        if (document.cookie && document.cookie != '') 
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) 
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) 
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                
            
        
        return cookieValue;
    
    function sameOrigin(url) 
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    
    function safeMethod(method) 
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) 
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    
);
</script>

其次,这是使用 jQuery 的基本 AJAX POST 的样子。请注意,它是基于防止我们模式中的表单的默认提交行为。成功后,我将新添加的值附加到表中。添加值作为捕获表单的一部分会不那么麻烦,但我希望确保在添加到表格之前所有内容都已保存和处理。

   $(document).ready(function() 
   $("#OptionForm").submit(function(event)
       event.preventDefault();
       $.ajax(
            type:"POST",
            url:"% url builder.views.addoption %",
            data: VariableID: $('input:hidden[name=VariableID]').val(), OptionLabel: $('input:text[name=OptionLabel]').val(), OptionValue: $('input:text[name=OptionValue]').val(),
            success: function(data)
            console.log(data['OptionID']);
            $("#OptionValueError").removeClass("error");  
            $("#OptionValueError span").text("");  
            $("#OptionValueError span").removeClass("error");
            $('#OptionTable > tbody:last').append('<tr id=Option_'+data['OptionID']+'><td>'+data['OptionValue']+'</td><td>'+data['OptionLabel']+'</td><td><a href="#" onClick="deleteOption('+data['OptionID']+')"><i class="icon icon-remove"></i></a>');
            $('input:text[name=OptionValue]').val('');
            $('input:text[name=OptionLabel]').val('');
            
          );
       );
    );

最后,您只需要捕获此 AJAX 请求的视图,如下所示。

def addoption(request):
    if request.is_ajax():
        OptionValue = int(request.POST['OptionValue'])
        OptionLabel = request.POST['OptionLabel']
        VariableID = int(request.POST['VariableID'])
        getVar = Variable.objects.get(id=VariableID)
        newOption = Option(VariableID=getVar,
                Value=OptionValue,
                Label=OptionLabel)
        newOption.save()
        response = 'OptionValue': OptionValue, 'OptionLabel': OptionLabel, 'OptionID': newOption.id
        json = simplejson.dumps(response)
        return HttpResponse(json, mimetype="text/json")
    else:
        pass

我们正在 json 序列化的响应字典是作为数据反馈的,随后用于将值附加到表中。无需重新加载主页。

希望这个例子有所帮助。如果您还有其他问题,请告诉我。

京东

【讨论】:

我喜欢你的回答,但我的问题最终是一个非常愚蠢的错字,如果你看上面的一个 id 是 #ajax_form_modal_result 而它应该是 ajax_form_modal_result :/

以上是关于使用 bootstrap 和 django 的异步表单的主要内容,如果未能解决你的问题,请参考以下文章

在本地使用 jQuery 和 Bootstrap for Django 不会响应

Django中使用Bootstrap展示树形结构

Django 和 Bootstrap:知道哪个选项卡处于活动状态

Django-引入Bootstrap

如何使用 Bootstrap 在 Django 中自定义复选框和收音机?

将 Django 和 Bootstrap 5 Modal 与 Ajax 结合使用