Bootstrap 模态表单发布两次 Django

2024-01-30

我正在按照以下指示进行操作django-bootstrap-modal-forms django-bootstrap-modal-forms https://pypi.org/project/django-bootstrap-modal-forms/我发现当我提交表单时,我的表单被发布或提交了两次。首先,该对象只是被创建了两次,我可以从管理员那里看到这一点。现在看来表单正在创建对象,但也进入其验证状态,如果表单成功(事实确实如此),我显然不希望出现这种状态。

有人经历过这个吗?除了我链接到的文档中概述的内容之外,我什么也没做,而且我无法确定为什么应该提交两次。

这是我的代码:

首页.html

<a href="#" class="create-shipment dropdown-itemcreatenew" onclick="closeNav()">Shipment</a>

<div class="modal fade" tabindex="-1" role="dialog" id="modal">
  <div class="modal-dialog" role="document">
    <div class="modal-content">

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

<script>
$(document).ready(function() {

    $(".create-shipment").modalForm({
        formURL: "{% url 'CreateShipmentView' %}"
    });

});
</script>

views.py

class CreateShipmentView(BSModalCreateView):
    template_name = 'create_shipment.html'
    form_class = CreateShipmentForm
    success_message = 'Success: Shipment Has Been Created!'
    success_url = reverse_lazy('HomeView')

create_shipment.html(模态表单模板)

{% load crispy_forms_tags %}
<form method="post" action="">
  {% csrf_token %}

 <div class="modal-header">
    <h5 class="modal-title">Create New Shipment</h5>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">
    {{form|crispy}}
  </div>

  <div class="modal-footer">
    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    <button type="button" class="submit-btn btn btn-primary">Create</button>
  </div>

</form>

forms.py

class CreateShipmentForm(BSModalForm):
    class Meta:
        model = Shipment
        fields = ['Reference_Number', 'Ultimate_Consignee']

urls.py

url(r'^create_shipment/', views.CreateShipmentView.as_view(), name='CreateShipmentView'),

提交按钮上的事件侦听器

 // Add click listener to the submitBtn
    var ajaxSubmit = function (modalID, modalContent, modalForm, formURL, errorClass, submitBtn) {
        $(submitBtn).on("click", function () {
            // Check if form.is_valid() via ajax request when submitBtn is clicked
            isFormValid(modalID, modalContent, modalForm, formURL, errorClass, submitBtn, submitForm);
        });
    };

    // Check if form.is_valid() & either show errors or submit it
    var isFormValid = function (modalID, modalContent, modalForm, formURL, errorClass, submitBtn, callback) {
        $.ajax({
            type: $(modalForm).attr("method"),
            url: $(modalForm).attr("action"),
            // Serialize form data
            data: $(modalForm).serialize(),
            success: function (response) {
                if ($(response).find(errorClass).length > 0) {
                    // Form is not valid, update it with errors
                    $(modalID).find(modalContent).html(response);
                    $(modalForm).attr("action", formURL);
                    // Reinstantiate click listener on submitBtn
                    ajaxSubmit(modalID, modalContent, modalForm, formURL, errorClass, submitBtn);
                } else {
                    // Form is valid, submit it
                    callback(modalForm);
                }
            }
        });
    };

更新到这篇文章:似乎软件包已更新并且原始问题已解决,因此此答案中的链接将不再指向您正确的代码/注释。如果您仍然遇到同样的问题,请先尝试升级软件包。


读完后源代码 https://github.com/trco/django-bootstrap-modal-forms/blob/master/bootstrap_modal_forms/static/js/jquery.bootstrap.modal.forms.js对于包裹,我认为后端收到两个请求是正常的。

你的代码

$(document).ready(function() {

    $(".create-shipment").modalForm({
        formURL: "{% url 'CreateShipmentView' %}"
    });

});

触发函数modalForm你的选择(formURL)并分配函数newForm到一个点击事件。

然后在newForm它调用函数的函数addListeners将点击事件绑定到模态中的提交按钮,事件调用如下:

isFormValid(modalID, modalContent, modalForm, formURL, errorClass, submitBtn, submitForm);

注意最后一个参数submitForm指向以下函数

var submitForm = function(modalForm) {
      $(modalForm).submit();
    };

最后在函数中isFormValid,您在表单中输入的所有数据都将发布到您在表单中定义的 urlaction属性进行验证,如果没有错误,表单将提交到完全相同的 url。

如果你深入研究这个包中的 python 代码,事情就会变得有趣。这BSModalForm基于两个类mixins.py and in here https://github.com/trco/django-bootstrap-modal-forms/blob/master/bootstrap_modal_forms/mixins.py#L40它表示当请求是由 ajax 以外的任何方式发出时,保存使用表单数据创建的实例,否则(如果由 ajax 调用请求)不保存实例并返回它。这就是为什么它首先验证表单但不应该保存它(记住第一个调用确实是通过使用 jQuery 中的 ajax 调用发起的)。

您提到表单被保存两次 - 尝试在保存函数的开头添加一行:

print(request.is_ajax())

然后检查输出。可能是呼叫无法作为 AJAX 呼叫发送。 (如果是这种情况,请更新您的jquery版本或使用其他东西来进行调用,例如axios)

如果你不喜欢事情发生的方式,有几个选择(在 MIT 许可证下打包):

  1. 改变save函数来验证实例,然后将其保存为普通的 django 保存函数,但这涉及更改一些 JS 代码。

  2. 创建一个API端点来接收数据并使用json进行通信,而不是每次都返回html代码(我想这也是作者以当前方式编写JS的原因,因为这样你就会面临渲染问题)。由于目前您在提交表单后不需要执行任何其他操作,因此返回实例不再有意义。 (不需要 DRF,因为 django 内置了一个 JsonResponse 类,并且如果您只需要这一个端点)

  3. 直接使用BootStrap,因为这里的故事相当简单:页面上的模态,触发模态的按钮,模态中的表单,然后您可以提交它。您可能需要编写一些自己的 JS 来显示错误,但这仍然比更改现有包更容易。


一个例子

# forms.py
from django import forms


# use django ModelForm for creating the form based on model
class CreateShipmentForm(forms.ModelForm):
    class Meta:
        model = Shipment
        fields = ['Reference_Number', 'Ultimate_Consignee']

用于呈现表单 (GET) 和接收表单提交 (POST) 的视图

# views.py
from yourapp.forms import CreateShipmentForm
from django.shortcuts import render


def create_shipment_view(request):
    # http POST request means that the form was submitted
    if request.method == 'POST':
        # create the form and map the data to CreateShipmentForm
        shipment_form = CreateShipmentForm(request.POST)
        # based on your design of the form/modal, validate the data passed into the form
        if shipment_form.is_valid():
            # create a new shipment object
            new_shipment = shipment_form.save()
            # form processing is finished now do something to alert user, for example redirect the user to the success page
            return redirect('success')
        # if the form is not valid, then shipment_form.errors contain all the errors
    else:
        # for all other accessing methods including GET
        # create an empty form
        shipment_form = CreateShipmentForm()
    
    # if the request was POST, the form contains errors, if request was GET, it's an empty form
    return render(request, 'path/to/template.html', {
        'form': shipment_form
    })

最后,在模板中,您可以像平常一样显示表单。如果您不知道或需要表单的其他功能,请继续使用脆皮表单。

check if shipment_form.errors如果您想向用户显示错误,请将其显示在您的模板中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Bootstrap 模态表单发布两次 Django 的相关文章

随机推荐

  • Java 反射:“java.lang.NoSuchMethodException”

    我试图使用反射从另一个类获取该方法 但由于某种原因 它一直给我一个没有这样的方法的异常 这些是我使用的类 脚本表类 for Class
  • git 存储库中二进制文件的高效存储

    我想要一个主要由二进制文件组成的 git 存储库 我需要跟踪存储库中已更改 添加和删除的文件 但我不希望 git 对文件本身的内容进行版本控制 换句话说 我只需要 git 来跟踪更改 更改日志 而不需要内容 这对于 git 来说是可能的吗
  • 重置选择器无法正确重置表数据

    我有一个带有多个选项的选择器和一个重置按钮 单击该按钮时必须将选择器重置为第一个选项 单击该按钮时将重置选择器 但表中的数据不会更改 这些是选择器和按钮
  • 用于在 Android 版 Firefox 中激活阅读器模式的书签

    最近 Android 上的 Firefox 发生了变化 这使得我无法使用向阅读列表添加内容并从那里打开它以强制页面进入阅读器模式的变通办法 考虑到这一点 我试图找到并最终制作一个小书签 以强制页面进入阅读器模式 到目前为止 我发现通过在 u
  • 如何使用 Google Apps 脚本替换电子表格中的文本?

    我想在电子表格中找到指定的文本并将其替换为其他单词 我这样尝试过 sheet SpreadsheetApp getActiveSheet sheet replaceText ga sessions Sessions 然后它说 Cannot
  • 后端使用Vite

    我们使用 Vite 作为前端 在 SvelteKit 内 它可以很好地创建 SSR 和前端代码 我特别喜欢通过 esbuild 预捆绑第 3 方软件包 有人可以告诉我是否可以将 Vite 捆绑管道用于仅后端项目 基于 koa 的 Nodej
  • iOS Swift Mi Scale 2 蓝牙称重

    我正在编写一个可以从小米米秤2获取体重测量的应用程序 读取所有可用的uuid后 只有 181B 连接 特别是 2A9C 特征 蓝牙GATT中的体重测量 收到通知 值数据为 2 164 178 7 1 1 2 58 56 253 255 24
  • 在 php-fpm/mod_fastcgi 中使用 mod_headers 时出现问题

    我正在尝试添加HSTS http en wikipedia org wiki HTTP Strict Transport Security我的应用程序中每个响应的标题 我的第一个想法是使用 mod headers 我将此指令放置在文档根目录
  • WCF REST 服务 POST 在 IIS 上返回 404 Not Found

    我在Win8上用VS2012创建了一个WCF服务 如果我通过 VS localhost port 启动服务 我就可以执行 GET 和 POST 操作 当我部署到同一台计算机上的 IIS 时 只有 GET 有效 POST 返回 404 Not
  • ListView:通过 Filterable 进行过滤与使用新 URI 重新启动 CursorLoader

    The ListView实现过滤内容的方法 您能详细说明一下什么时候应该使用它吗 据我了解 这种过滤适用于基于数组的适配器 所有数据都已经在内存中 这样 过滤器只是帮助跳过不应该显示的数据 然而 如果ListView与游标适配器 SQLit
  • 清单合并失败:uses-sdk:minSdkVersion 8 不能更小

    问题是 Error Execution failed for task app processDebugManifest 清单合并失败 uses sdk minSdkVersion 8 不能小于库 com android support s
  • 运行 showdown.js 服务器端将 Markdown 转换为 HTML(在 PHP 中)

    我正在尝试在我的网站上实现 WMD 并且想知道如何运行 showdown js 服务器端以将 markdown 转换为 HTML 为了将两者存储在数据库中 我正在使用 PHP 任何提示都会有帮助 之前从未从 php 运行过任何类型的 js
  • 升级到 AngularDart 0.13.0 并收到有关路由和 di 的错误

    我升级到 AngularDart 0 13 0 但收到以下错误 使用新的路由模块初始化 RoutingModule 的正确方法是什么di包2 0 1 In main dart I have class RoutingModule exten
  • 运行时异常 (Chromecast)

    我尝试配置 Chromecast 但收到 RuntimeException 并且不明白原因 Fabric 有日志 致命异常 java lang RuntimeException 无法启动活动 ComponentInfo activity T
  • 在 Google App Engine 上使用 Python 验证 Android 应用内购买消息的签名

    Android 开发人员网站上的示例应用程序使用 java 代码验证购买 json 有没有人有幸弄清楚如何用 python 验证购买 特别是在 GAE 中 以下是android应用内计费的相关摘录示例程序 http developer an
  • 模式浏览器不显示我在 Solr 中添加到 schema.xml 中的字段

    我在 solr v5 1 中创建的名为 Core3 的核心的 schema xml 中添加了一些字段 我不是指示例文件夹 而是使用 服务器 文件夹来运行 solr 服务器并创建 solr 核心 我使用 bin 文件夹中提供的 solr cr
  • MVVM Light WPF 打开新窗口

    我是 MVVM 新手 正在使用 MVVM Light 学习它 我在 wpf 中有一个带有登录窗口的应用程序 当用户输入正确的凭据时 登录窗口应关闭并应打开一个新的主窗口 登录部分已经可以工作 但是如何打开一个新窗口并关闭当前窗口 login
  • F# 中的命令式多态性

    OCaml 的 Hindley Milner 类型系统不允许命令式多态性 类似于 System F 除非通过最近对记录类型的扩展 这同样适用于 F 然而 有时需要将用命令式多态性 例如 Coq 编写的程序翻译成此类语言 Coq 的 OCam
  • Rails 5 多个清单文件的问题

    我的问题 在我的 Rails 5 应用程序中 我有 2 个布局 因此我需要设置多个清单文件 我做了什么 我做了以下事情 The two layouts have a user html erb and a main html erbhtml
  • Bootstrap 模态表单发布两次 Django

    我正在按照以下指示进行操作django bootstrap modal forms django bootstrap modal forms https pypi org project django bootstrap modal for