当后端表单验证失败时,如何在 jQuery 对话框中重新打开 Django 表单?

How to reopen a Django form in a jQuery dialog when the form validation fails in the backend?

我有一个 Django 表单,在用户单击网页上的链接后,我将其动态加载到 jQuery 对话框中。链接中的 href 指向一个 Django 页面,该页面仅包含表单内容,而不是整个站点布局。

1
2
3
4
5
6
7
8
9
10
        $('#add-note').click(function() {
            $('#dialog').load($(this).attr('href')).dialog({
                title: 'Add a note',
                modal: true,
                draggable: false,
                minWidth: 500,
            });

            return false;
        });

如果用户提交在后端进行验证的表单,这会正常工作。但是,如果表单包含验证错误,Django 会将浏览器转发回表单页面,在这种情况下,该页面实际上并不是用户当前正在查看的页面。

看,用户在一个完全不同的页面上,表单只是动态加载到 jQuery 对话框中。所以问题是,处理这种情况的最佳方法是什么?如何将带有验证错误的表单打开回对话框而不是表单页面本身?

非常感谢所有帮助!


当使用 AJAX 和 Django 表单时,我通常采用以下方法(虽然没有代码示例,但我想你会明白的)。

  • 创建一个不同的模板来呈现这个表单(没有块,没有从另一个模板扩展)
  • 在呈现模板以显示表单的视图中,通过 django.template.loader.render_to_string(使用我提到的模板)将此表单直接呈现为 html。将此呈现的表单放入上下文中,将其推送到模板。
  • 在您的模板中,为表单创建一个容器并在其中呈现 html。
  • 当您现在通过 AJAX 提交表单时,请确保提交表单的处理程序也呈现表单(就像在您通过 django.template.loader.render_to_string 的原始视图中一样)并至少将其作为 html 返回。如果表单无效,thls 将包含错误。
  • 获得 AJAX 响应时,只需完全替换容器中的表单即可。之后,您将获得包含原始 django 表单提交的所有错误的 Django 表单。

这种方法的优点是 Django 仍在处理表单验证和错误显示,您不需要通过 Javascript 处理它(可能有点烦人,尤其是字段错误)。缺点当然是你必须为它编写更多的后端代码。 :)


如果表单无效,我会返回一个错误以及一条消息,而不是返回 200、success 等。在视图中,它是这样的:

1
2
3
4
5
if form.is_valid():
    ...hooray!
else:
    return HttpResponse(json.dumps({'error': msg}), status=400,
                        mimetype='application/json')

在我刚刚发出的 ajax 请求中,请求将失败,我将在某处(通常在对话框中)向用户显示错误,并且 javascript 将如下所示:

1
2
3
4
5
6
7
8
9
$.ajax({
  type: 'POST',
  data: form,
  error: function(data) {
    var error = $.parseJSON(data.responseText);
    $('#error').text(error.error);
    $('#error').show();
  }
});

一个快速而肮脏的非 ajax 解决方案是:

1
2
3
4
5
$(function() {
    {% if form.errors %}
        $("#form" ).dialog("open" );
    {% endif %}
});

或者如果你有一个表单集:

1
2
3
{% if formset.is_bound and not formset.is_valid %}
    $("#formset" ).dialog("open" );
{% endif %}

注意:formset.errors 将始终为真(如果没有任何错误,它是一个空字典列表),因此您必须以这种方式使用 is_bound 和 is_valid,否则您将始终在提交表单集后打开对话框.

编辑:
这实际上并不能完全回答原始问题。我看到您的表单是从不同的 url 加载的。如果您在同一视图中处理表单并且您只是在同一页面上的 jQuery 对话框中显示它,我的解决方案确实有效。