【问题标题】:How do I insert a django form in twitter-bootstrap modal window?如何在 twitter-bootstrap 模式窗口中插入 django 表单?
【发布时间】:2012-07-01 19:55:18
【问题描述】:

四月份有人问过确切的same question,没有任何答案。但由于他提供的信息太少;这个问题被放弃了。

我也有同样的问题。在main_page.html 内我有这行:

<a href="/contact/edit/{{ item.id }}" title="Edit">edit</a>

单击此处后,编辑模板将出现在 twitter 引导模式中。

url.py

(r'^contact/edit/(?P<contact_id>\d+)/$', contact_view),

view.py

def contact_view(request, contact_id=None):
    profile = request.user.get_profile()
    if contact_id is None:
        contact = Contact(company=profile.company)
        template_title = _(u'Add Contact')
    else:
        contact = get_object_or_404(profile.company.contact_set.all(), pk=contact_id)
        template_title = _(u'Edit Contact')
    if request.POST:
        if request.POST.get('cancel', None):
            return HttpResponseRedirect('/')
        form = ContactsForm(profile.company, request.POST, instance=contact)
        if form.is_valid():
            contact = form.save()
            return HttpResponseRedirect('/')
    else:
        form = ContactsForm(instance=contact, company=profile.company)
    variables = RequestContext(request, {'form':form, 'template_title': template_title})
    return render_to_response("contact.html", variables)

contact.html 通常是这样的:

        <form class="well" method="post" action=".">
            {% csrf_token %}
            {{form.as_p}}
            <input class="btn btn-primary" type="submit" value="Save" />
            <input name="cancel" class="btn" type="submit" value="Cancel"/>
        </form>

我可以把它放在&lt;div class="modal-body"&gt; 中。 但是,我如何从视图中打开模态?

【问题讨论】:

    标签: django forms twitter-bootstrap modal-dialog


    【解决方案1】:

    当我遇到这篇文章时,我遇到了同样的问题。我尝试了这个解决方案,但它并没有真正为我工作(但它给了我方向)。我想出了一个对我有用的解决方案,但是感觉很笨拙,我想收到一些关于如何做得更好的建议。

    问题是一样的:在 twitter boostrap modal 和 django 表单中显示一个表单(使用 django 通用表单视图为我编辑/添加模型)

    所以我做了什么:

    main.html

    <script type="text/javascript">
        function genericLoadDialog(form_selector, dialog_selector, matchString){
            $.ajax({
                url: $(form_selector).attr('action'),
                type: 'POST',
                data:  $(form_selector).serialize(),
                success: function(data, textStatus, jqXHR){
                    if(data.match(matchString)){
                    // We got errors in form
                        $(dialog_selector).html(data).modal('show');
                                return false;
                    }
                            $(dialog_selector).modal('hide');
                },
            })
        }
    </script>
    
    <body>
    <div class="modal hide" id="{{ editor_dialog_id }}"></div>
    <a data-toggle="modal" href="#{{ editor_dialog_id }}" onclick="$('#{{ editor_dialog_id }}').load('/create/form');">Title</a>
    <body>
    

    editor.html

    <form id="{{ editor_form_id }}" action="{{ submit_url }}" method="POST">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal">×</button>
            <h3>Modal header</h3>
        </div>
        <div class="modal-body" id="editor-dialog-body">
            {% if not form.is_valid %}
                <div class='hide'>invalid_form</div>
            {% endif %}
            {% csrf_token %}
            {{ form.as_p }}
        </div>
        <div class="modal-footer">
           <a href="#" class="btn" data-dismiss="modal">Cancel</a>
           <a href="#" data-toggle="modal" class="btn btn-primary" onclick="genericLoadDialog('#{{ editor_form_id }}', '#{{ editor_dialog_id }}', null, 'invalid_form');">Save</a>
        </div>
    </form>
    

    所以流程是这样的:

    • 点击标签将表单从创建表单 url 加载到模态 div 中
    • 在触发 genericLoadDialog 函数的模式(提交)中单击保存按钮。此加载使用从表单收集的数据向创建表单 url 发出 POST 请求
    • 如果表单无效,它将重新加载模态 html 并显示错误字段,否则关闭模态并 django 应保存/重定向(我在 django 表单视图中使用 get_success_url 方法,但由于某种原因对我不起作用。它确实保存对象)

    我对在 genericLoadDialog 中检查表单是否有效的方式感到不舒服,如果有人有更好的想法会很好。

    【讨论】:

    • 感谢您提供此解决方案。我现在将开始研究它。由于上述解决方案仅在您没有收到任何验证错误的情况下才有效。
    • 经过进一步评估,您的示例似乎不起作用。您的 javascript 接受三个参数并传入四个。一般不清楚。
    【解决方案2】:

    除非您需要在模式之外使用联系表单,否则这应该适合您。如果您确实需要在其他地方使用它,请维护两个版本(一个是模态的,一个不是)。另外,提示 - 给 django-crispy-forms 一个外观 - 它可以帮助您使用 twitter-bootstrap 类呈现表单。

    contact.html:

    <div class="modal hide" id="contactModal">
    <form class="well" method="post" action="/contact/edit/{{ item.id }}">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">×</button>
        <h3>Editing Contact</h3>
      </div>
      <div class="modal-body">
           {% csrf_token %}
           {{form.as_p}}
      </div>
      <div class="modal-footer">
           <input class="btn btn-primary" type="submit" value="Save" />
           <input name="cancel" class="btn" type="submit" value="Cancel"/>
      </div>
    </form>
    </div>
    

    main_page.html

    <html>
    ...
    
    <a data-toggle="modal" href="#contactModal">Edit Contact</a>
    
    {% include "contact.html" %}
    
    ...
    </html>
    

    编辑:

    好的,既然我知道您可能有多个表单,那么将每个表单隐藏在 html 中呈现可能是个坏主意。您可能想要使用 ajax-y 版本,并按需加载每个表单。 我假设在提交表单时,整个页面都会重新加载。如果要异步提交表单,别处有答案

    我们将从重新定义contact.html 片段开始。它应该在模态中呈现,并包含与模态良好配合所需的所有标记。您最初拥有的 contact 视图很好 - 除了如果表单是无效,您最终将呈现 contact.html 而不是其他任何东西。

    <form class="well contact-form" method="post" action="/contact/edit/{{ item.id }}">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">×</button>
        <h3>Editing Contact</h3>
      </div>
      <div class="modal-body">
           {% csrf_token %}
           {{form.as_p}} <!-- {{form|crispy}} if you use django-crispy-forms -->
      </div>
      <div class="modal-footer">
           <input class="btn btn-primary" type="submit" value="Save" />
           <input name="cancel" class="btn" type="submit" value="Cancel"/>
      </div>
    </form>
    

    现在,你的main_page.html

    <html>
    .. snip ..
    
    <a class="contact" href="#" data-form="/contact/edit/{{ item.id }}" title="Edit">edit</a>
    <a class="contact" href="#" data-form="/contact/edit/{{ item.id }}" title="Edit">edit</a>
    <a class="contact" href="#" data-form="/contact/edit/{{ item.id }}" title="Edit">edit</a>
    
    <div class="modal hide" id="contactModal">
    </div>
    
    <script>
        $(".contact").click(function(ev) { // for each edit contact url
            ev.preventDefault(); // prevent navigation
            var url = $(this).data("form"); // get the contact form url
            $("#contactModal").load(url, function() { // load the url into the modal
                $(this).modal('show'); // display the modal on url load
            });
            return false; // prevent the click propagation
        });
    
        $('.contact-form').live('submit', function() {
            $.ajax({ 
                type: $(this).attr('method'), 
                url: this.action, 
                data: $(this).serialize(),
                context: this,
                success: function(data, status) {
                    $('#contactModal').html(data);
                }
            });
            return false;
        });
    </script>
    
    .. snip ..
    </html>
    

    这一切都未经测试,但它应该为您提供一个开始/迭代的好地方。

    【讨论】:

    • 感谢 Josh 提供的出色解决方案。模态仍然是空的。我看不到实际呈现的表单。我认为是因为它是直接从 main_page.html 打开的,而不是从视图中打开的。因此没有创建表单实例。 :( 就像鸡肉和鸡蛋一样。我也会按照你的建议研究酥脆的形状......
    • @Kave 您需要确保将表单从主/索引视图传递到 main_html 模板。否则,请考虑使用jQuery.load 使用现有的contact_view 加载html 片段。我的回答是假设您只使用contact_view 处理表单(并重定向回您的主/索引),并使用您的主视图进行渲染。您想使用 ajax 处理联系表单,还是重新加载整个页面?显然,我将很多事情留给你,但你的选择是从 main 渲染,或者使用 ajax 来渲染和处理部分。
    • 谢谢乔希。让我们尝试进一步澄清这一点。 main_page.html 是索引页面,显示所有保存的联系人,可以删除或编辑。如果用户点击第二个项目的编辑,他将被重定向到/contact/edit/2,而这又在 url.py 中被捕获并委托给我们的contact_view。在那里它将搜索请求的联系人 ID 并将其实例化为一个表单对象,该对象在 contact.html 中呈现。因此,在main_page.html 中,表单甚至无法存在,因为在首先重定向到视图之前,我们甚至还没有联系人对象。
    • @Kave,您的视图函数已经接受contact_id,只需将其作为变量传递到您的RequestContext,并使用that 而不是{{ item.id }}。简单。很高兴能提供帮助。
    • @Kave,django 期望到处都有斜杠。您可能有一个 django 设置 ADD_TRAILING_SLASH (我认为它被称为)导致重定向发生 - 我不确定 jQuery.load 如何处理重定向(可能不太好)。如果可能,请避免使用form.initial,这只是一种解决方法。很高兴这一切都对你有用。
    猜你喜欢
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 2013-11-10
    • 2019-11-18
    • 2012-10-10
    • 2011-12-13
    相关资源
    最近更新 更多