【问题标题】:Preventing django form to refresh whole page on submit防止 django 表单在提交时刷新整个页面
【发布时间】:2019-10-22 20:05:45
【问题描述】:

我在 Django 中有一个嵌入在引导模式元素中的表单。表单的输入是一个客户 ID,我检查它是否在数据库中。提交时一切正常,除非客户端 ID 不在数据库中,页面会重新加载,我必须再次打开模式元素才能看到错误消息。

我试图通过向我的 html 添加脚本来简单地防止页面刷新:

$('#modalform').on('submit', function (e) {
        e.preventDefault();
    })

但这会破坏提交时的表单行为。

我的 home.html 中带有表单的模态 div 如下所示:

<div class="modal fade" tabindex="-1" role="dialog" id="mymodal" aria-labelledby="myLargeModalLabel">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-body">
                <form action="" method="POST" id="modalform">
                    {% csrf_token %}

                    {% if form.non_field_errors %}
                        <div class="alert alert-danger" role="alert">
                            {% for error in form.non_field_errors %}
                                {{ error }}
                            {% endfor %}
                        </div>
                    {% endif %}

                    {% for field in form.visible_fields %}
                        <div class="form-group">
                            {{ field.label_tag }}

                            {% if form.is_bound %}
                                {% if field.errors %}
                                    {% render_field field class="form-control is-invalid" %}
                                    {% for error in field.errors %}
                                        <div class="invalid-feedback">
                                            {{ error }}
                                        </div>
                                    {% endfor %}

                                 {% else %}
                                     {% render_field field class="form-control is-valid" %}
                                 {% endif %}
                             {% else %}
                                 {% render_field field  class="form-control" %}
                             {% endif %}
                         </div>
                     {% endfor %}

                <input class="btn btn-primary" type="submit" value="submit">
            </form>
        </div>
    </div>
</div>

view.py 中的视图如下所示:

def home(request):
    if request.method == "POST":
        print("POST")
        form = SelectClient(request.POST)

        if form.is_valid():
            url = reverse(
                "client",
                kwargs={"client_id": form.cleaned_data["client_id"]},
            )
            return HttpResponseRedirect(url)

    else:
        form = SelectClient()
        print("GET")

    return render(request, "app/home.html", {"form": form})

表格如下所示:

class SelectClient(forms.Form):
    client_id = forms.CharField(label="Client ID")

    def clean_client_id(self):
        data = self.cleaned_data["client_id"]

        if Client.objects.filter(client_id=data).exists():
            print("Success!")
        else:
            print("No such client!")
            raise ValidationError(
                _("No such client!")
            )

        return data

urls.py 看起来像这样:

urlpatterns = [
    path("", views.home, name="app-home"),
    path(
        "client/<str:client_id>",
        views.client,
        ),
]
  1. 我能否在提交不在数据库中的 client_id 时实现这一点,页面不会完全重新加载,而只是在不使用 ajax 的情况下更新错误消息?

  2. 如果不是:如果我想要所需的行为,添加的 ajax 代码会是什么样子?

我的第一个想法是这样的:

$('#modalform').on('submit', function (e) {
        e.preventDefault();

        $.ajax({
            type: 'POST',
            url: '/home/',
            data: {
                client_id: $('#client_id').val(),
                csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
            },
            success: function () {
                alert("Client found, but what now?!");
            },
            error: function () {
                alert("Client not found, but what now?!")
            }
        })

    })

【问题讨论】:

  • 您是否在控制台中看到任何错误?如果是,则粘贴它。
  • 如果你想使用 ajax,你的视图应该检查 request.is_ajax() 并在这种情况下返回一个 JsonResponse (表单有效和无效),在字典中返回一个状态码(' ok' 或 'errors')和额外的信息来告诉你的脚本做什么:例如成功时重定向到的 url,或者向用户显示的错误。
  • 查看here,了解如何处理 ajax 请求的一个很好的例子。
  • @AakashTushar 没有错误,因为这是预期的行为。我只是想改变行为。
  • @dirkgroten 我想我以前见过request.is_ajax() 方法。当我发回提到的 JSON 响应时,a) 处理有效与无效情况以及 b) 如果响应无效则更新表单的正确方法是什么?您提到的链接忽略了这一点(尽管它是一个很好的资源!)

标签: jquery ajax django django-forms bootstrap-modal


【解决方案1】:

你想检查是否有表单错误(你可以做一个特定的字段),如果有则弹出模式

<script>
    {% if form.errors %}
        document.getElementById("mymodal").showModal(); 
    {% endif %}
</script>

【讨论】:

  • 这是解决问题的最简单方法,即使需要重新加载页面。如果您想完全避免页面重新加载并在模式中获得无缝体验,那么使用 ajax 是您的最佳选择。
  • 使用@HenryM 的代码时出现错误:Uncaught TypeError: document.getElementById(...).showModal is not a function
  • 因为你给你的模态ID mymodal - 我已经修改了
  • 它适用于$("#mymodal").modal("show");,但正如@dirkgroten 所述,它仍然会重新加载页面
  • 它将重新加载页面,因为您的错误检查在服务器上。如果您不想重新加载页面,则需要在 JS 中进行错误检查
【解决方案2】:

因为我发现在这种情况下很难使用 Django Forms,所以我更明确地解决了这个问题。

我的新test_form 表单:

<form id="test_form">
    {% csrf_token %}
    <div class="form-group">
        <label for="client_id">Client ID:</label>
        <input class="form-control" id="client_id" placeholder="Client ID" />
        <div class="form-text text-danger" id="form-error"></div>
    </div>
    <input class="btn btn-primary" type="submit" value="submit">
</form>

我的新 test_form 表单的 Javascript:

$('#test_form').on('submit', function (e) {
        e.preventDefault();

        $.ajax({
            type: 'POST',
            url: 'ajax/testform/',
            data: {
                client_id: $('#client_id').val(),
                csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
            },
            success: function (data) {

                console.log(data["status"])
                if (data["status"] == "valid") {
                    window.location.href = "/client"
                }
                if (data["status"] == "invalid") {
                    $("#form-error").html(data["message"]);
                    $("#client_id").addClass("is-invalid")
                }
            },
            error: function () {
                alert("Error!")
            }
        })

    })

还有新的testform 视图:

def testform(request):
    if request.method == "POST":
        form = SelectClient(request.POST)

        if request.is_ajax():
            if form.is_valid():
                data = {"status": "valid", "client_id": form.cleaned_data["client_id"]}

            else:
                data = {
                    "status": "invalid",
                    "client_id": form.data["client_id"],
                    "message": form.errors["client_id"],
                }
        else:
            data = {"message": "not an ajax call"}
        return JsonResponse(data)

有什么反对这个解决方案的吗?这是一种好的做法吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-02
    • 2012-09-14
    • 1970-01-01
    • 2020-06-29
    • 2016-01-18
    • 2012-04-01
    • 1970-01-01
    相关资源
    最近更新 更多