本文给出的例子均以flask和python为基础,本人也还处于学习阶段,可能会有错误或者不全的地方,请见谅。
一、前端向后端发送数据
1.1 form表单
前端代码如下:
<form class="form-box" id="loginForm" name="frmlogin" action="/" method="post" >
<div class="choose clearfix">
<span>选择身份</span>
<div class="choose-one">
<input type="radio" value="xs" name="type" checked="">
<lable>学生</lable>
</div>
<div class="choose-one">
<input type="radio" value="js" name="type">
<lable>教师</lable>
</div>
</div>
<div class="name">
<div class="form-input input-name">
<input name="username" id="username" type="text">
</div>
<div class="form-input input-code">
<input name="password" id="password" type="password">
</div>
</div>
<div class="btns clearfix">
<button id="submit_id" type="submit">登 录</button>
</div>
</form>
这是一个登录表单,需要从前端传到后端的主要有两个数据:用户名和密码。虽然代码中有身份的选择,但是为了方便起见,忽略掉身份信息,只查看用户名和密码的数据传递。
后端代码如下:
@student.route("/student", methods=["POST","GET"])
def get_view():
id = request.form.get('username')
password = request.form.get('password')
stu = Student.query.get(id)
if not stu:
return render_template('login_new.html', error="用户名或密码错误")
student_id = id
student_name = stu.name
if stu != 'None' and stu.password == password:
return render_template("demo.html", name=student_name, id=student_id)
else:
return render_template('login_new.html', error="用户名或密码错误")
在这里我以学生身份进行了一个简单示范,可能有人注意到,前端表单代码中给出的==action==的值为"/"而后端接收的路由为"/student",这是因为我在前端对身份选择进行了一个判断来改变表单的==action==值。
可以看到flask后端是通过request.form.get()来取得表单里面的值,request是flask库中的一个模块。
需要注意的是,get方法是通过前端input标签里的==name==属性得到的,不是==id==,再次强调是==name==,不是==id==。
身份判断代码:
<script type="text/javascript">
function changeUrl(){
var val=document.getElementsByName("type");
if(val[0].checked){
document.getElementById('loginForm').action='student';
}
if(val[1].checked){
document.getElementById('loginForm').action='teacher';
}
}
</script>
1.2 axios数据交互
前端代码如下:
<div class="bl-content" id="test">
<h2 style="color: #0e0e0e">尝试一下</h2>
<div class="col-3 input-effect" style="width: 40%">
<input type="text" placeholder="第一句" v-model="sentence1">
<span class="focus-border">
<i></i>
</span>
</div>
<div class="col-3 input-effect" style="width: 40%">
<input type="text" placeholder="第二句" v-model="sentence2">
<span class="focus-border">
<i></i>
</span>
</div>
<button class="btn-1" @click="compute_sentence()">计算</button>
</div>
从代码可以看出前端有两个文本输入框,要求用户输入两个句子,然后将这两个句子传到后端计算这两个句子的文本相似度。按钮组件也绑定了vue中的相关点击事件。通过v-model直接将输入文本框的值与vue的data属性里面的值关联起来,实现数据的双向绑定。
vue中methods代码如下:
compute_sentence:function(){
var obj=this;
if (obj.sentence1=="" || obj.sentence2 == "") {
swal({
title: "输入错误!",
text: "",
icon: "error",
button: "确认"});
}
else {
axios.get('/compute_test?sentence1='+obj.sentence1+'&sentence2='+obj.sentence2).then(
function(response){
var data=response.data;
obj.semantic_matching_val=data["semantic_matching_val"];
obj.text_match_val = data["text_match_val"];
obj.answer = data["answer"];
obj.total_score = data["total_score"]
})}}
代码中将==this==的值赋给obj,使得obj可以访问vue中的data里面的参数。通过axios.get设置好路由和参数,将数据传递给后端。
后端代码如下:
@search.route('/compute_test', methods=["POST", "GET"])
def compute_test():
sentence1 = request.args["sentence1"]
sentence2 = request.args["sentence2"]
text_match_val = text_match_cal2.cal_text_match_for_one(sentence1, sentence2)
semantic_matching_val = semantic_matching_cal.cal_text_match(sentence1, sentence2)
rate = float(semantic_matching_val) * 0.25 + 0.75
total_score = rate * text_match_val
if total_score >= 0.8:
answer = "文本相似度较高"
if 0.8 > total_score >= 0.6:
answer = "文本相似度一般"
if total_score < 0.6:
answer = "文本相似度较低"
result = {
"text_match_val": text_match_val,
"semantic_matching_val": semantic_matching_val,
"answer": answer,
"total_score": total_score
}
return jsonify(result)
后端通过request.args取得跟随路由传递过来的参数,该方法同样适用于a标签的==href==属性的情况。
中间的代码是关于文本相似度的计算,可以忽略掉,但是为了代码的完整性,我还是贴出来了。
关于文本相似度的计算,最终得到四个相关结果,需要将这四个结果传到前端,首先要将这四个值保存为字典类型,通过jsonify将这个字典转换成json格式,然后return即可。
在上面的vue代码中,通过response.data得到这个json格式的数据,然后格局键值对取得相应数据即可。
二、后端向前端发送数据
flask中后端主动向前端传递数据主要是依靠jinja2的模板引擎,而这也是flask自带的。
2.1简单的信息传递
后端代码如下:
@student.route("/student", methods=["POST","GET"])
def get_view():
id = request.form.get('username')
password = request.form.get('password')
stu = Student.query.get(id)
if not stu:
return render_template('login_new.html', error="用户名或密码错误")
student_id = id
student_name = stu.name
if stu != 'None' and stu.password == password:
return render_template("demo.html", name=student_name, id=student_id)
else:
return render_template('login_new.html', error="用户名或密码错误")
还是以之前的登录为例,当用户名或密码错误时,需要在前端显示错误信息,这时函数的返回值==render_template==的参数中多了一项==error==.
前端代码如下:
<p style="color:red">{{error}}</p>
而前端可以通过jinja2的模板语法{{}}取得error参数对应的文本信息。
2.2 javascript接收后端的值
后端代码如下:
@manager.route('/', methods=['POST', 'GET'])
def get_view():
global type_num, types
stus = GoodsList.query.group_by(GoodsList.type).all()
type_num = len(stus)
for i in range(0, len(stus)):
types.append(stus[i].type)
name_list = [] # 统计历史数据
stus2 = NumberList.query.all()
history_number = {}
for i in range(0, len(stus2)):
number = [stus2[i].day1, stus2[i].day2, stus2[i].day3, stus2[i].day4, stus2[i].day5, stus2[i].day6,
stus2[i].day7]
history_number[stus2[i].name] = number
name_list.append(stus2[i].name)
date_list = get_week()
info = {
'history_number': history_number,
'date_list': date_list
}
return render_template('index.html', name=name_list, history_number_json=json.dumps(info))
这里给出的是仓库进出货管理系统一个例子,首页需要展示在库商品的相关数据,中间的代码时访问数据库得到商品的种类,近一周进出库的数量等信息。将其这些信息封装成字典形式,render_template函数中设置相应的参数,json.dumps将字典数据转换成json数据。
前端代码如下:
<script>
data ={{history_number_json|safe}}
var date_list = data['date_list']
var number_list = data['history_number']
<\script>
这里的语法涉及到jinja2的过滤器,将history_number_json的值赋给data,然后分别取出相应的值。
2.3 后端数据在前端展示
还是上面的那个例子,在传送给前端的值中除了history_number_json外还有name,并且name的值并非json格式,而是列表格式,存放的是各商品的名称。
前端代码如下:
{%for i in name%}
<div class="chart">
<div class="row">
<div class="col-lg-6 pr-lg-2 chart-grid">
<div class="card text-center card_border">
<div class="card-header chart-grid__header">
{{i}}柱状图
</div>
<div class="card-body">
<!-- bar chart -->
<div id="container">
<canvas id="barchart{{loop.index}}"></canvas>
</div>
<!-- //bar chart -->
</div>
<div class="card-footer text-muted chart-grid__footer">
昨日更新
</div>
</div>
</div>
<div class="col-lg-6 pl-lg-2 chart-grid">
<div class="card text-center card_border">
<div class="card-header chart-grid__header">
{{i}}曲线图
</div>
<div class="card-body">
<!-- line chart -->
<div id="container">
<canvas id="linechart{{loop.index}}"></canvas>
</div>
<!-- //line chart -->
</div>
<div class="card-footer text-muted chart-grid__footer">
昨日更新
</div>
</div>
</div>
</div>
</div>
<!-- //charts -->
{%endfor%}
jinja2模板提供了循环,判断语法,这里给出了循环语法的使用。这只是对单一列表的遍历,还可以对字典或者多列表的遍历语法。其中loop.index循环计数内置变量,loop.index0是从0开始,loop.index是从1开始。
关于jinja2的更深层次的使用建议去看看官方文档。