python - 将 JSON 发布到烧瓶模板
问题描述
我一直在努力想办法首先从我的搜索中获取 JSON 数据(谢天谢地我现在已经解决了),然后用喷出的 JSON 数据更新我的 jinja 模板。
我尝试了一些方法,但我似乎在绕圈子,因为我对 AJAX 或 Flask 都不是很有经验,所以我往往会导致比我能解决的问题更多的问题。
我有一个 AJAX 文件,但我不相信它正在工作(如果它甚至是正确的)但我猜这需要被指示获取数据并将其放入渲染模板的正确表/区域中?我的问题是我怎样才能做到这一点?
下面是我的 app.py
from flask import request, jsonify
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
from flask import render_template
from sqlalchemy import create_engine
from flask_marshmallow import Marshmallow
import json
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']='postgresql://postgres:test@localhost/postgres'
engine = create_engine('postgresql+psycopg2://postgres:test@localhost/postgres')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.debug = True
app.config['SQLALCHEMY_ECHO'] = True
db=SQLAlchemy(app)
Bootstrap(app)
ma=Marshmallow(app)
# classes
class Sdctest(db.Model):
startchass= db.Column (db.Text, primary_key=True)
cusname= db.Column (db.Text)
chassistype1= db.Column (db.Text)
axleqty= db.Column (db.Integer)
tyres= db.Column (db.Text)
extlength= db.Column (db.Text)
neck= db.Column (db.Text)
stepheight= db.Column (db.Text)
reardeckheight= db.Column (db.Text)
siderave= db.Column (db.Text)
steer= db.Column (db.Text)
sockets= db.Column (db.Text)
containerstwistlock= db.Column (db.Text)
headboard= db.Column (db.Text)
class TableSchema(ma.Schema):
class Meta:
fields = ('startchass', 'cusname', 'chassistype1', 'axleqty', 'tyres', 'extlength', 'neck', 'stepheight', 'reardeckheight', 'siderave', 'steer', 'sockets', 'containerstwistlock', 'headboard')
tables = TableSchema()
tabless = TableSchema(many=True)
#routes
@app.route('/')
def index():
return render_template('index.html')
@app.route('/platform', methods=['GET', 'POST'])
def curtainsider():
options = db.session.query(Sdctest.chassistype1).distinct().all()
axleopts = db.session.query(Sdctest.axleqty).distinct().all()
# enables passing user input to the variable
if request.method == 'POST':
# query parameters and their corresponding database columns
param_columns = {
"startchass": "startchass",
"cusname": "cusname",
"chassistype1": "chassistype1",
"axleqty": "axleqty",
"tyres": "tyres",
"siderave": "siderave",
"steer": "steer",
"sockets": "sockets",
"containerstwistlock":"containerstwistlock",
"headboard": "headboard",
}
param_column2 = {
"startchass": "startchass",
"extlength": "extlength",
"neck": "neck",
"stepheight": "stepheight",
"reardeckheight": "reardeckheight",
}
# Get all of the column filters where the parameters aren't empty
filters = {
column: request.form[param]
for param, column in param_columns.items()
if request.form.get(param, "") != ""
}
filters2 = {
column: request.form[param]
for param, column in param_column2.items()
if request.form.get(param, "") != ""
}
#filter most columns using fuzzy match
query = Sdctest.query
for column, value in filters.items():
query = query.filter(getattr(Sdctest, column).ilike(f'%{value}%')) .order_by(Sdctest.startchass.desc())
for column, value in filters2.items():
query = query.filter(getattr(Sdctest, column).ilike(f'{value}')).order_by(Sdctest.startchass.desc())
results2 = query.all()
result2 = tabless.dump(results2, object)
# renders the template
return render_template('platform.html')
return jsonify(result2)
else:
return render_template('platform.html', options=options)
if __name__ == "__main__":
run_server()`
这是我的模板:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<style>
body {
padding: 15px;
background-image: url("/static/bg.png");
background-repeat: no-repeat;
}
.table-hideable td,
.table-hideable th {
width: auto;
transition: width .5s, margin .5s;
}
.btn-condensed.btn-condensed {
padding: 0px 0px 0px 0px;
box-shadow: none;
}
.hide-col {
width: 0 !important;
height: 0 !important;
display: none !important;
overflow: hidden !important;
margin: 0 !important;
padding: 0 !important;
border: none !important;
}
.thbg
{
background-image: url("/static/fieldbg.png");
}
.thbgg
{
background-color:#b21f2d ;
color: #FFF;
}
</style>
<link rel="stylesheet" href={{ url_for('static', filename='css/bootstrap.css') }}>
<script defer src="https://use.fontawesome.com/releases/v5.0.13/js/all.js" integrity="sha384-xymdQtn1n3lH2wcu0qhcdaOpQwyoarkgLVxC/wZ5q7h9gHtxICrpcaSUfygqZGOe" crossorigin="anonymous"></script>
<meta charset="UTF-8">
<title>Sales Search</title>
</head>
<body>
<div id="wrapper">
<div class="corner-ribbon top-left red shadow">ALPHA</div>
<div align="center" class="p"><img src="/static/sdclogopng.png"> </div>
<div class="container-fluid" id="container-fluid">
<div class="row">
<div class="col-sm-9">
<div class="form-group">
<form method="POST" class="form-horizontal" role="form" name="form" id="form">
<div class="form-row form-group">
<div class="col-auto">
<input type="text" name="startchass" class="form-control form-control-sm thbg" placeholder="Chassis Number">
</div>
<div class="col-auto">
<input type="text" name="cusname" class="form-control form-control-sm thbg" placeholder="Customer name">
</div>
<div class="col-auto">
<select name="chassistype1" class="form-control form-control-sm thbg" title="chassis type">
<option disabled selected value>Select chassis type</option>
{% for option in options %}
<option class="form-control form-control-sm thbg" value="{{ option[0] }}">{{ option[0] }}</option>
{% endfor %}
</select>
</div>
<div class="col-auto">
<select name="axleqty" class="form-control form-control-sm thbg" title="chassis type">
<option disabled selected value>Axle quantity</option>
{% for axleopt in axleopts %}
<option class="form-control form-control-sm thbg" value="{{ axleopt[0] }}">{{ axleopt[0] }}</option>
{% endfor %}
</select>
</div>
<div class="col-auto">
<input type="text" name="tyres" class="form-control form-control-sm thbg" placeholder="tyre type" id="1">
</div></div>
<div class="form-row form-group">
<div class="col-auto">
<input type="text" name="extlength" class="form-control form-control-sm thbg" placeholder="External Length" id="2">
</div>
<div class="col-auto">
<input type="text" name="neck" class="form-control form-control-sm thbg" placeholder="Neck Dimensions" id="3">
</div>
<div class="col-auto">
<input type="text" name="stepheight" class="form-control form-control-sm thbg" placeholder="Step height" id="3">
</div>
<div class="col-auto">
<input type="text" name="reardeckheight" class="form-control form-control-sm thbg" placeholder="reardeckheight" id="4">
</div>
<div class="col-auto">
<input type="text" name="siderave" class="form-control form-control-sm thbg" placeholder="Siderave" id="5">
</div></div>
<div class="form-row form-group">
<div class="col-auto">
<input type="text" name="steer" class="form-control form-control-sm thbg" placeholder="Steer option" id="6">
</div>
<div class="col-auto">
<input type="text" name="sockets" class="form-control form-control-sm thbg" placeholder="Socket count" id="7">
</div>
<div class="col-auto">
<input type="text" name="containertwistlock" class="form-control form-control-sm thbg" placeholder="Twist locks" id="8">
</div>
<div class="col-auto">
<input type="text" name="headboard" class="form-control form-control-sm thbg" placeholder="headboard" id="9">
</div>
<input type="submit" value="Search" class="btn btn-danger btn-sm" id="button" name="button" type="button"></div>
</form>
</div></div><div class=col-sm-3> <div class="refinewidth"> <h6 style="color:#fff">search for specific items/text here:</h6>
<input class="form-control form-control-sm thbg" id="myInput" type="text" placeholder="Search.."></div><br></div></div></div>
<div class="col-sm-4 alert alert-info"><strong>Click on a column header to exclude it from your results</strong></div>
{% block body %}
<div class="table-responsive">
<table class="table table-condensed table-hover table-bordered table-hideable table-sm">
<thead class="table-hideable thbgg">
<tr>
<th class="hide-column">Chassis Number </th>
<th class="hide-column">Customer name</th>
<th class="hide-column">Chassis Type</th>
<th class="hide-column">Axles</th>
<th class="hide-column">Tyre</th>
<th class="hide-column">External Length</th>
<th class="hide-column">Neck</th>
<th class="hide-column">Step height</th>
<th class="hide-column">Rear Deck height</th>
<th class="hide-column">Siderave</th>
<th class="hide-column">Steer</th>
<th class="hide-column">Sockets</th>
<th class="hide-column">Twistlocks</th>
<th class="hide-column">Headboard</th>
</tr>
</thead>
<tbody id="myTable">
{% for item in result2 %}
<tr>
<td class>{{ item.startchass }}</td><td>{{ item.cusname }}</td><td>{{ item.chassistype1 }}<td>{{ item.axleqty }}</td><td>{{ item.tyres }}</td><td>{{ item.extlength }}</td><td>{{ item.neck }}</td><td>{{ item.stepheight }}</td><td>{{ item.reardeckheight }}</td><td>{{ item.siderave }}</td><td>{{ item.steer }}</td><td>{{ item.sockets }}</td><td>{{ item.containerstwistlock }}</td><td>{{ item.headboard }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot class="show-column-footer">
<tr>
<th colspan="14"><a class="show-column" href="#">Click here to show hidden columns</a></th>
</tr>
</tfoot>
</table>
</div>
{% endblock %}
<script>
$(document).ready(function(){
$("#myInput").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>
<script type=text/javascript src="{{ url_for('static', filename='ajax.js') }}"></script>
<script type=text/javascript src="{{ url_for('static', filename='form.js') }}"></script>
</div>
</body>
</html>
最后是我的(可能不工作的)AJAX 文件:
$(function() {
$('form').on('submit', function(e){
$.ajax({
url: '/platform',
data: $('form').serialize(),
type: 'POST',
cusname:cusname,
success: function(response) {
console.log(response);
},
error: function(error) {
console.log(error);
}
});
});
});
解决方案
我不完全理解您要实现的目标,但我猜您尝试使用搜索框输入并使用这些输入来查询数据库并将 JSON 返回到表中?如果这不是您想要达到的目标,请回答我在上面评论过的四个问题。另外,我强烈建议您在搜索框中使用某种验证,因为它直接进入您的查询 (DB)。您可以使用 Flask-WTF(服务器端表单验证 - 更好)甚至客户端表单验证库(较弱)。
考虑到上面是你的情况,下面是最小化的例子。
阿贾克斯
$(function() {
// please do not use form as an ID as this may be a potential error later on.
$('#form').on('submit', function(e){
$.ajax({
url: '/platform', //not a good practice to use /platform, but instead use "{{url_for('.curtainsider')}}"
data: $('form').serialize(), //removed cusname, if you need to pass cusname into the server, create a hidden input field and include it inside <form></form>
type: 'POST',
success: function(response) {
var dbData = response.result;
// do your thing here with the data that was passed from curtainsider()
},
error: function(error) {
console.log(error);
}
});
});
});
看法
@app.route('/platform', methods=['GET', 'POST'])
def curtainsider():
# to parse the serialized form.
if request.method == 'POST':
data_one = request.form['data_one']
cusname = request.form['cusname']
# and so on....
# make DB queries based on your input
return jsonify({'result': db_data})
下面是受 CSRF 保护的情况。
如果您的表单受 CSRF 保护,请将以下代码附加到 ajax 函数的末尾。并且还包括{{form.csrf_token}}
在 HTML 中的表单元素中。
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", "{{ form.csrf_token._value() }}")
}
}
});
推荐阅读
- android - 如何从 Android 的 ESC/POS 机器上减少字体和删除下划线?
- c++ - VideoWrite 不写
- asp.net-core - 无法在 Razor Pages 代码隐藏类中使用注入类
- security - 将 IP 地址列入白名单时,我可以信任 X-Forwarded-For 标头值吗?
- javascript - 在令牌更新时更新横向组件?
- date - Windows 10 工具栏。不仅仅是显示文件夹内容
- c# - 在 C# 中访问 SRSS 数据
- python - 在 df 中使用基于列 vale 的字典中的值创建新列
- javascript - 如何使用 jquery 选择框更改计算总运费?
- swift - 标题中的不同标签取决于集合视图中的部分