flask 表单提交问题,如何实现点击执行执行按钮,执行下拉框选择的部分
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flask 表单提交问题,如何实现点击执行执行按钮,执行下拉框选择的部分相关的知识,希望对你有一定的参考价值。
if request.form['selectA'] == 'QA2':
print 'qa2---------------'
elif request.form['selectA'] == 'UAT':
print 'UAT---------------'
<form name="runTest" id="runTest" action="/index" method="POST" style="display: inline-block;">
<table width="50%" border="1" bordercolorlight="#000000" bordercolordark="#FFFFFF" bgcolor="#CCFFCC" cellpadding="4" align="left">
<tr>
<td colspan="2"> <div align="center" style="width: 800px;"><b>接 口 测 试</b></div> </td>
</tr>
<tr>
<td colspan="2">选择测试环境:<select name = 'select' id ='select' style="width: 100px;">
<option value="0"></option>
<option value="1">QA2</option>
<option value="2">UAT</option>
</select>
<input type="submit" name="submit" value="Do Something Else">
</td>
</tr>
</table>
</form>
以上总是报错The browser (or proxy) sent a request that this server could not understand.
后台可以获取下拉框的值啊,然后判断一下,在点击执行运行吧,刚学的,,不太懂
后台可以获取下拉框的值啊,然后判断一下,在点击执行运行吧,刚学的,,不太懂
本回答被提问者和网友采纳为啥两次点击按钮时这个表单没有提交两次?
【中文标题】为啥两次点击按钮时这个表单没有提交两次?【英文标题】:Why is this form not submitted twice when hitting the button twice?为什么两次点击按钮时这个表单没有提交两次? 【发布时间】:2018-12-23 03:51:31 【问题描述】:编辑 25.07.2018: 正如 Pawnesh Kumar 在回答中所说,这似乎是浏览器问题。如果我在 Firefox 中多次点击该按钮,下面的脚本只会发送一个 POST
请求,但如果我在 Chrome 中执行相同操作,则每次点击都会收到一个 POST
请求。
但是,我可以在 01:00 在video 中复制该问题。这意味着当我使用Authentication 安装 Laravel 时,如果我点击登录表单中的提交按钮两次,Firefox 将发送 2 个请求。
为什么在多次单击按钮时,Firefox 有时会发送多个 POST
请求,有时只发送一个?
我有一个用户表
id | name
1 | John
其中字段id
是一个主、整数、自动递增键。当我提交一个只有一个按钮的虚拟表单时,这将插入一条名为 John
的新记录。现在这是我观察到的:
如果我提交一次表单,返回浏览器再次提交,然后 我在数据库中发现了两个新行。
如果我通过在Add
上单击两次(或二十次)提交表单
按钮,那么数据库中只有一个新行。
这是为什么呢?我希望如果我多次点击提交按钮,那么表单将发送多个请求 - 并插入多行。
这是我的表格:
<form action="/test.php" method="POST">
<input type="submit" value="Add">
</form>
提交给test.php
:
<?php
$servername = "localhost";
$username = "adam";
$password = "password";
$dbname = "test-db";
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "INSERT INTO user (name) VALUES ('John')";
if ($conn->query($sql) === TRUE)
echo "New record created successfully";
$conn->close();
sleep(4);
由于sleep
部分,我可以连续多次单击Add
按钮。但是,无论我在加载时单击Add
按钮的频率如何,数据库中都只有一个新行。
在我的 access.log 文件中,单击按钮二十次后,我还发现只有一个 GET
和 POST
请求:
2001:****:****:4400:****:****:****:**** - - [25/Jul/2018:11:30:03 +0200] "GET /test/form.php HTTP/1.1" 200 301 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0" "****** *.net"
2001:****:****:4400:****:****:***:**** - - [25/Jul/2018:11:30:34 + 0200]“POST /test/test.php HTTP/1.1”200 31“http://********.net/test/form.php”“Mozilla/5.0(X11;Ubuntu;Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0" "********.net"
备注:
我已经阅读过有关防止多次提交的技术 在backend 或frontend 中。因此我认为应该可以通过多次点击按钮来多次提交表单。
我还在 wiki 文章 Post/Redirect/Get 中读到,如果用户过快地多次提交表单,这种模式无法阻止:
如果由于服务器延迟导致网络用户在初始提交完成之前刷新,导致某些用户代理中出现重复的 POST 请求。
同样在video 1:00 有人双击一个按钮并收到错误,因为他提交了两次。
【问题讨论】:
所以,您已经深入挖掘了,只是想确定一下, csrf_field()
是否真的在页面重新加载时发生了变化?
@Eakethet 我编辑了这个问题,希望现在更清楚
@Adam 更多,太好了。不知道在 Firefox 中如何,但它应该与在 chrome 中相同。当您疯狂地点击提交按钮二十次时,打开网络监视器并查看事件是如何触发的。该事件被取消,它只需要最后一个事件。多次单击将适用于 - 1) 滞后,2) ajax 表单提交
@Eakethet 如果您疯狂地点击提交按钮,您会说只接受最后一个事件。但是,如果您考虑我在评论中提到的视频,那么您会发现用户在 1:00 单击了两次提交按钮并出现错误 - 这是因为第一个帖子刷新了会话中的令牌,第二个提交了令牌与表单中隐藏字段中的令牌不同。所以在这种情况下,第一个帖子没有被取消。
您使用的是哪个版本的 PHP?
【参考方案1】:
注意:我不是专家,所以我可能是错的。这只是我的看法。
对我来说,这似乎是浏览器的怪癖。 Firefox 似乎故意忽略了所有额外的请求。
铬
对于 Chrome,如果您多次单击添加按钮,则会向服务器发送多个请求。最初,由于服务器没有响应,所有额外的请求都被取消(您可以了解更多关于 canceled
here 的信息)。但是,一旦服务器响应(即,一旦睡眠时间结束),所有请求都会立即处理。我不知道为什么,但服务器只为第一个请求休眠。其余请求将立即处理。
边缘
如果您多次单击该按钮,Edge 也会发送多个请求。
火狐
Firefox 有点奇怪。无论您单击按钮多少次,它都只会发送一个请求。所有额外的请求都会被忽略。
【讨论】:
是的,但即使是 Firefox 也可以通过多次点击发送多个 post 请求。这是我不明白的缺失部分。【参考方案2】:这是一个浏览器的事情。
我相信您说的是用户多次单击按钮时的情况。在后台页面开始重新加载。
当我们点击提交按钮时,浏览器将请求发送到服务器。直到响应收到一些浏览器显示旧的(过期)页面,同时一些简单的清理视图。
在 Firefox 中,即使点击了很多次,它也不会触发任何事件。其中Chrome每次用户点击时都会向服务器提交请求。
因此,最重要的是浏览器处理事物的方式。你的日志也显示了你使用 Firefox 这样的情况。
【讨论】:
我不认为它是浏览器的事情。因为在某些脚本上,当我多次单击该按钮时会发送多个请求。例如,如果我安装了一个 Laravel 应用程序并尝试在 01:00 像在https://www.youtube.com/watch?v=gJRv2ahMzEg
中那样单击登录按钮两次登录,那么我会收到相同的错误消息。因此,在 Laravel 示例中,单击按钮两次会发送两个请求,而在我上面的小示例中则不会。我不知道它是什么,但不可能只是因为浏览器。
好的,我用 Chrome 和你的权利测试了它。在 Chrome 中,它使用上面的示例脚本为每次点击发送一个 POST 请求。但是为什么我可以从Firefox中的视频中重现双重提交的问题?
我在 Firefox 中没有找到。我做的和视频中的完全一样,但不是那个错误,而是我在表单字段中得到一个正常的验证错误。
您需要先注册一个带有姓名和密码的电子邮件(在标签注册处)。然后在登录表单中使用相同的电子邮件和密码。双击登录按钮应该会给你 Firefox 中的错误。
我找到了解决方案!在 Laravel 中,重定向到 home 部分。这意味着当您第一次按下按钮时,会直接发送 POST
请求,然后是 GET
请求。现在,如果您再次按下该按钮,Firefox 将接受下一个 POST
请求,因为在最后一个 POST
之间是一个 get。什么是重温的理解。谢谢!【参考方案3】:
-
您怎么知道您的表单没有提交两次或更多次?
您在数据库中没有多行这一事实并不能证明这一点。也许列“名称”在您的表中是唯一的?
-
检查您的网络服务器的日志。 Apache 示例:
sudo cat /var/log/apache2/access.log
在那里你会找到你收到多少请求的信息。
【讨论】:
感谢您提及 access.log!我检查了它并确认只有一个请求(请参阅编辑的问题)。数据库的名称不是唯一的。在分析 access.log 之前,我相信只有一个请求,因为当我提交表单时,返回并再次提交时,我在数据库中发现了两行(请参阅我对问题的观察中的第 1 点)。 【参考方案4】:这可能是因为您使用flock
专门锁定了一个文件LOCK_EX
,然后尝试使用file_put_contents
写入它,这在后台打开了一个带有fopen
的新指针,因为您已经锁定了该文件完全无法写入您的文件。
尝试将file_put_contents
替换为fwrite($fp, $current, strlen($current))
,并在fopen
中添加一个附加标志,例如fopen($file, a+)
这会重现多次写入的问题吗?
更新
由于 Laravel 的 CSRF 保护,您提供的视频中的令牌异常不匹配发生。
Laravel 中的每个表单都需要有一个 csrf_field()
,或者您需要在 AJAX 请求的 Header 中提供 crsf_token
。
表单隐藏字段中的 csrf_token
与 Laravel 的用户会话中存储的值相同。当您在表单上双击快速提交时,第一个请求与第一个 csrf_token
一起发送,当它到达 Laravel 时,将比较表单请求中发送的令牌和会话中存储的令牌,如果它们相等则请求通过,并在会话中生成一个新的csrf_token
。
由于您没有重新加载视图,因此新令牌无法在隐藏表单字段中呈现,因此当第二个请求命中时,我们在会话中有一个新的 csrf_token
,而在第二个表单中是旧的请求,因此抛出异常。
更新 2
正如我所说的flock
,试试这个代码,多重提交问题就可以解决
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST')
$file = 'file.txt';
$fp = fopen($file, 'a+');
if (flock($fp, LOCK_EX))
fwrite($fp, "+", 1);
flock($fp, LOCK_UN);
sleep(2);
?>
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<form action="/" method="POST">
<button type="submit">Submit</button>
</form>
</body>
</html>
【讨论】:
你是对的,file_put_contents
创建了另一个锁。但这不是这里的问题。如果那会是个问题,那么一开始就不可能写任何东西来罚款。但正如我在评论中所说 - 如果我“只是”在数据库中插入一行或发送邮件,这个问题也存在。它与锁无关。
等一下file_put_content
默认不创建LOCK:php.net/manual/de/function.file-put-contents.php
但是你在调用file_put_contents
之前已经锁定了文件flock($fp, LOCK_EX)
,所以你不能写入文件,存在排他锁,file_put_contents
打开另一个指针背景,无法写入,因为您已经在上面锁定了一行。
首先,我真的很感谢您在这里为我提供了如此多的帮助。我真的希望你是对的,因为我真的很想知道这里发生了什么。但是,我认为您错过了有关羊群的一些事情。您可以始终使用fwrite
或fopen
或file_put_content
- 无论文件是否被锁定,都可以独立使用。 flock 只是一个咨询锁定。如果你的论点是正确的,那么就根本不可能用我的脚本向文件中写入一些东西,但显然它是。
我从 Update 2 尝试了您的脚本,如果我多次单击提交按钮,文件中仍然只添加了一个 +
。这次我将再次使用数据库更改我的问题,因此flock
的事情将不再让人们感到困惑。不过,感谢您的帮助!以上是关于flask 表单提交问题,如何实现点击执行执行按钮,执行下拉框选择的部分的主要内容,如果未能解决你的问题,请参考以下文章
在前台怎么通过js实现表单提交后,判断该提交调用的Action方法是不是执行完成了