javascript - Python Flask + HTML如何在URL中显示选定的参数
问题描述
我有一个 python 烧瓶应用程序,我想知道如何让 html 页面显示从下拉列表、文本框、多选等中选择的参数。
我当前工作设置的一个玩具示例如下所示:
app.py
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html",
selection1=["1","2"],
selection2=["1","2"],
)
@app.route("/get-values")
def get_values():
dummy = [
["123", "123", "123"],
["456", "456", "456"],
["789", "789", "789"],
]
result = {
'sessions': dummy,
'total_sessions': 3,
'total_pages': 1,
'current_page': 1
}
return jsonify(result)
if __name__ == '__main__':
app.run(debug=True)
步骤基本上是:
index.html
包含用户可以更新参数以使表格显示不同信息的页面当您打开页面时,它会显示默认选择的结果
每当您更新任何字段时,结果将自动更新(通过使用
$('#selection1-field').on('change', getFirstPageValues);
更新是通过调用
/get-values
并app.py
发送新参数来完成的。
我现在要做的是能够使用更新的参数保存(在浏览器中添加书签)url。目前它只保存http://localhost:5000/
主页以及显示结果的位置,但我希望它能够保存带有更新参数的 url,以便下次打开书签页面时,它已经应用了参数,像:http://localhost:5000/get-values?c1=v1&c2=v2&c3=v3
。
我想我需要有类似 getUrlParam 的东西(如何从 GET 参数中获取值?)但我对 js 很陌生,我不知道该怎么做。也可能我需要在 python 烧瓶端进行更改?
另一个问题是,由于主 url 是索引(/
),但我正在调用不同的端点(/get-values
)来获取表的数据,如果我要使用类似的东西http://localhost:5000/get-values?c1=v1&c2=v2&c3=v3
,那么根据当前的设置,我基本上只是保存json 输出而不是 json 输出结果的表格显示页面。理想情况下应该是http://localhost:5000/c1=v1&c2=v2&c3=v3
,但我不知道如何进行这项工作,也找不到任何参考资料。
对应index.html
如下。你应该能够把它放在下面/templates
并使应用程序工作。它具有function displayResults(result)
用于显示表格的内容。
<!doctype html>
<html>
<head>
<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'>
<link rel='stylesheet' href='//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css' />
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.4/css/bootstrap-select.min.css'>
<style type='text/css'>
.CSSTableGenerator {
margin: 50px;
padding: 0px;
width: 95%;
border: 1px solid #000000;
-moz-border-radius-bottomleft: 0px;
-webkit-border-bottom-left-radius: 0px;
border-bottom-left-radius: 0px;
-moz-border-radius-bottomright: 0px;
-webkit-border-bottom-right-radius: 0px;
border-bottom-right-radius: 0px;
-moz-border-radius-topright: 0px;
-webkit-border-top-right-radius: 0px;
border-top-right-radius: 0px;
-moz-border-radius-topleft: 0px;
-webkit-border-top-left-radius: 0px;
border-top-left-radius: 0px;
}
.CSSTableGenerator table {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
.CSSTableGenerator tr:last-child td:last-child {
-moz-border-radius-bottomright: 0px;
-webkit-border-bottom-right-radius: 0px;
border-bottom-right-radius: 0px;
}
.CSSTableGenerator table tr td {
-moz-border-radius-topleft: 0px;
-webkit-border-top-left-radius: 0px;
border-top-left-radius: 0px;
}
.CSSTableGenerator table tr:first-child td:last-child {
-moz-border-radius-topright: 0px;
-webkit-border-top-right-radius: 0px;
border-top-right-radius: 0px;
}
.CSSTableGenerator tr:last-child td:first-child {
-moz-border-radius-bottomleft: 0px;
-webkit-border-bottom-left-radius: 0px;
border-bottom-left-radius: 0px;
}
.CSSTableGenerator tr:hover td {
}
/*.CSSTableGenerator tr:nth-child(odd) {
background-color: #aad4ff
}
.CSSTableGenerator tr:nth-child(even) {
background-color: #ffffff
}*/
.CSSTableGenerator td {
vertical-align: middle;
border: 1px solid #000000;
border-width: 0px 1px 0px 0px;
text-align: left;
padding: 7px;
font-size: 13px;
font-family: Arial;
font-weight: normal;
color: #000000;
}
.CSSTableGenerator tr:last-child td {
border-width: 0px 1px 0px 0px
}
.CSSTableGenerator tr:last-child td:last-child {
border-width: 0px 0px 0px 0px
}
.CSSTableGenerator tr:first-child th {
background: -o-linear-gradient(bottom, #005fbf 5%, #003f7f 100%);
background: -webkit-gradient( linear, left top, left bottom, color-stop(0.05, #005fbf), color-stop(1, #003f7f) );
background: -moz-linear-gradient( center top, #005fbf 5%, #003f7f 100% );
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#005fbf", endColorstr="#003f7f");
background: -o-linear-gradient(top,#005fbf,003f7f);
background-color: #005fbf;
border: 0px solid #000000;
text-align: center;
border-width: 0px 0px 1px 1px;
font-size: 14px;
font-family: Arial;
font-weight: bold;
color: #ffffff;
}
.CSSTableGenerator tr:first-child td:first-child {
border-width: 0px 1px 1px 0px
}
.CSSTableGenerator tr:first-child td:last-child {
border-width: 0px 0px 1px 1px
}
#radial-center {
/* fallback */
background-color: #2F2727;
background-position: center center;
background-repeat: no-repeat;
/* Safari 4-5, Chrome 1-9 */
/* Can't specify a percentage size? Laaaaaame. */
background: -webkit-gradient(radial, center center, 0, center center, 460, from(#1a82f7), to(#2F2727));
/* Safari 5.1+, Chrome 10+ */
background: -webkit-radial-gradient(circle, #1a82f7, #2F2727);
/* Firefox 3.6+ */
background: -moz-radial-gradient(circle, #1a82f7, #2F2727);
/* IE 10 */
background: -ms-radial-gradient(circle, #1a82f7, #2F2727);
/* Opera couldn't do radial gradients, then at some point they started supporting the -webkit- syntax, how it kinda does but it's kinda broken (doesn't do sizing) */
}
td {
vertical-align: top;
}
.content {
width: 650px;
}
.sidebar {
width: 300px;
}
.leftNavButton {
width: 190px;
line-height: 1;
}
/* Start by setting display:none to make this hidden.
Then we position it in relation to the viewport window
with position:fixed. Width, height, top and left speak
speak for themselves. Background we set to 80% white with
our animation centered, and no-repeating */
/* When the body has the loading class, we turn
the scrollbar off with overflow:hidden */
body.isloading {
overflow: hidden;
}
/* Anytime the body has the loading class, our
modal element will be visible */
body.isloading .mymodal {
display: block;
}
.pace .pace-progress {
background: red;
position: fixed;
z-index: 2000;
top: 0;
left: 0;
height: 5px;
-webkit-transition: width 1s;
-moz-transition: width 1s;
-o-transition: width 1s;
transition: width 1s;
}
.pace-inactive {
display: none;
}
.ignoreDetailsRow {
cursor: pointer
}
.mistagDetailsRow {
cursor: pointer
}
.fixDetailsRow {
cursor: pointer
}
.ignoreSummaryRow {
cursor: pointer
}
.fixSummaryRow {
cursor: pointer
}
.mistagSummaryRow {
cursor: pointer
}
pre {
outline: 1px solid #ccc;
padding: 5px;
margin: 5px;
background-color: #000;
}
.string {
color: white;
}
.number {
color: darkorange;
}
.boolean {
color: blue;
}
.null {
color: magenta;
}
.key {
color: gold;
}
/* shirokov additions */
* {
-webkit-border-radius: 3 !important;
-moz-border-radius: 3 !important;
border-radius: 3 !important;
}
.container {
width: 95%;
}
.bootstrap-select > .dropdown-toggle {
width: 100%;
padding-right: 25px;
}
</style>
<title>Test</title>
</head>
<body>
<div id='homepage-container' class='container body-container' style='width: 1500px;'>
<div id='title-div' class='row' style='margin-bottom: 30px;'>
<h1 class='title' style='text-align: center; margin-top: 30px;'>Test</h1>
</div><!-- title-div -->
<div id='form-div' class='row' style='margin-bottom: 30px;'>
<div class='form-holder'>
<form id='query-form'>
<div class='col-lg-1 col-md-1'></div>
<div class='col-lg-2 col-md-2'>
<label id='date-range'>Date</label>
<div id='reportrange' class='pull-right' style='background: #fff; cursor: pointer; padding: 5px 8px; border: 1px solid #ccc; width: 100%'>
<span id='date-field'></span> <b class='caret'></b>
</div>
</div>
<div class='col-lg-1 col-md-1'>
<label>Selection1</label>
<select class='form-control' id='selection1-field'>
{% for d in selection1 %}
<option value="{{ d[0] }}">{{ d[1] }}</option>
{% endfor %}
</select>
</div>
<div class='col-lg-2 col-md-2'>
<label>Selection2</label>
<select id='selection2-field' class='selectpicker form-control' name='selection2' title='All' multiple data-live-search='true' style='width: 100%;'>
{% for d in selection2 %}
<option value='{{ d }}'> {{ d }}</option>
{% endfor %}
</select>
</div>
<div class='col-lg-2 col-md-2'>
<label>Query Search</label>
<input type="text" class="form-control" id="query-search-field">
</div>
</form>
</div><!-- form-holder -->
</div><!-- form-div -->
<div id='result-div' class='row' style='margin-bottom: 30px;'>
<p class='result-num' id='fetching' style='margin-left: 50px;'></p>
<table border="0" cellpadding="0" width="100%" id='result-table'> </table>
<p class='result-num' style='margin-left: 50px;'></p>
</div><!-- result-div -->
</div><!-- homepage-container -->
<script src='https://code.jquery.com/jquery.js'></script>
<script src='//cdn.jsdelivr.net/momentjs/latest/moment.min.js'></script>
<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'></script>
<script src='//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.4/js/bootstrap-select.min.js'></script>
<script type='text/javascript'>
$(function() {
var start = moment().year(2019).month(10).day(1);
var end = moment().year(2019).month(10).day(5);
function cb(start, end) {
$('#reportrange span').html(start.format('MMMM DD, YYYY') + ' - ' + end.format('MMMM DD, YYYY'));
getFirstPageValues();
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
alwaysShowCalendars: true,
opens: 'right',
ranges: {
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
}
}, cb);
cb(start, end);
});
function displayResults(result) {
$('.result-num').empty();
$('#result-table').empty();
if ((result == 'ERROR: memory exceeded') || (result == 'ERROR: no results found for given parameters') || (result == 'ERROR: invalid date range')) {
$('#result-table').append(result);
} else {
var sessions = result['sessions'];
var totalSessions = result['total_sessions'];
var totalPages = result['total_pages'];
var currentPage = result['current_page'];
console.log(sessions[0]);
// setup table
var table = $("<table id=\'result-table\' />").addClass('CSSTableGenerator');
var row1 = $("<tr/>");
row1.append($("<td/>").text("C1"));
row1.append($("<td/>").text("C2"));
row1.append($("<td/>").text("C3"));
table.append(row1);
for (var i=0, len=sessions.length; i<len; i++) {
for (var j=0, len2=sessions[i].length; j<len2; j++) {
var c1 = sessions[i][j][0];
var c2 = sessions[i][j][1];
var c3 = sessions[i][j][2];
row = $("<tr/>").css("border-top", "1px solid #d6d6d6");
row.append($("<td/>").text(c1));
row.append($("<td/>").text(c2));
row.append($("<td/>").text(c3));
table.append(row);
}
}
$('.result-num').append('Total sessions: ' + totalSessions.toString() + '<br/>');
$('.result-num').append('Showing page ' + currentPage.toString() + ' out of ' + totalPages.toString() + '<br/>');
if (currentPage == 1) {
$('.result-num').append('<a href="" id="nextpage-btn" class="clickable" data-page="' + currentPage + '" data-action="next">>> Next Page</a>');
} else if (currentPage == totalPages) {
$('.result-num').append('<a href="" id="prevpage-btn" class="clickable" data-page="' + currentPage + '" data-action="prev"><< Prev Page</a>');
} else {
$('.result-num').append('<a href="" id="prevpage-btn" class="clickable" data-page="' + currentPage + '" data-action="prev">Prev Page <<</a> <a href="" id="nextpage-btn" class="clickable" data-page="' + currentPage + '" data-action="next">>> Next Page</a>');
}
$('#result-table').append(table);
var nextPageBtn = document.querySelectorAll('#nextpage-btn');
for (var i = 0; i < nextPageBtn.length; i++) {
nextPageBtn[i].addEventListener('click', function(evt) {
goToNextPage(evt);
});
}
var prevPageBtn = document.querySelectorAll('#prevpage-btn');
for (var i = 0; i < prevPageBtn.length; i++) {
prevPageBtn[i].addEventListener('click', function(evt) {
goToPrevPage(evt);
});
}
}
}
function getFirstPageValues() {
$('.result-num').empty();
$('#result-table').empty();
$('#fetching').append('Fetching results...');
var formInputs = {
'date': $('#date-field').html(),
'selection1': $('#selection1-field').val(),
'selection2': JSON.stringify($('#selection2-field').val()),
'querypattern': $('#query-search-field').val(),
'page_num': 1
};
$.get('/get-values',
formInputs,
displayResults
);
}
$('#selection1-field').on('change', getFirstPageValues);
$('#selection2-field').on('change', getFirstPageValues);
$('#query-search-field').on('change', getFirstPageValues);
function goToNextPage(evt) {
evt.preventDefault();
var formInputs = {
'date': $('#date-field').html(),
'selection1': $('#selection1-field').val(),
'selection2': JSON.stringify($('#selection2-field').val()),
'querypattern': $('#query-search-field').val(),
'page_num': parseInt(document.getElementById('nextpage-btn').dataset.page) + 1
};
$.get('/get-values-ns',
formInputs,
displayResults
);
}
function goToPrevPage(evt) {
evt.preventDefault();
var formInputs = {
'date': $('#date-field').html(),
'selection1': $('#selection1-field').val(),
'selection2': JSON.stringify($('#selection2-field').val()),
'querypattern': $('#query-search-field').val(),
'page_num': parseInt(document.getElementById('prevpage-btn').dataset.page) - 1
};
$.get('/get-values',
formInputs,
displayResults
);
}
</script>
</body>
</html>
解决方案
我现在要做的是能够使用更新的参数保存(在浏览器中添加书签)url。目前它只保存 http://localhost:5000/这是主页以及显示结果的位置,但我希望它能够保存带有更新参数的 url,以便下次打开书签页面时,它已经应用了参数,例如: http://localhost:5000/get-values?c1=v1&c2=v2&c3=v3。
您将需要 JavaScript。当您修改选择框中的值时,您需要更新查询字符串,以便在为它添加书签时为正确的 url 添加书签。
然后在 /get-values 路由中,需要使用 request.args.get('c1') 等来获取值。
推荐阅读
- flutter - 用户注销时如何在 Flutter 中处理 StreamProvider 的值?
- java - 如何在后台执行任务?
- wpf - WPF Datagrid Button commandParameter 在后面的代码中
- css - 样式中的 HTL 条件
- sql-server - 在 SQL Select 语句中读取 XML 值
- flutter - 最新文档未在 Firestore 中列出
- node.js - 将 Strapi 部署到 Heroku 时出现应用程序错误,但构建成功?
- python - 函数中的 task.loop 没有显示任何错误,但也无法正常工作
- python - 将张量向量附加到张量矩阵
- python-3.x - Keras-Tuner 运行时错误