1、自己实现一例flask项目;
2、在flask中,如何调用json传值;
3、进一步读懂现有代码。
Flask 在整个系统中是作为一个后台框架,对外提供 api 服务,因此对它的理解学习要保持足够严谨,因为将来必然会遇到性能问题。
![Flask标志](https://i-blog.csdnimg.cn/blog_migrate/1dd27f04e1689108abb328ae21537f97.png)
1、第一行代码
![508489-20180510191633461-904959231.png](https://i-blog.csdnimg.cn/blog_migrate/fa690022b0055e2122fb92306accdb18.png)
回显
![508489-20180510191633674-466911596.png](https://i-blog.csdnimg.cn/blog_migrate/037d6ce67dcbaf76741b406590e71523.png)
![508489-20180510191633880-46235908.png](https://i-blog.csdnimg.cn/blog_migrate/f8c8e67b68efaca1d2c2d75afa13b605.png)
代码里面,显而易见是使用了路由,这样可以进一步看清楚
![508489-20180510191634141-1651372052.png](https://i-blog.csdnimg.cn/blog_migrate/3d36dbc63bc73743f081c8ca768393ee.png)
![508489-20180510191634385-681093437.png](https://i-blog.csdnimg.cn/blog_migrate/0e5d661ddb8bab66e89c17b52add851c.png)
路由也可以更复杂一些,但是现在应该不会用到
![508489-20180510191634663-1516006544.png](https://i-blog.csdnimg.cn/blog_migrate/bb4f98f20170a3d1c199af9a1dd79410.png)
如果需要处理具体的HTTP方法,在Flask中也很容易,使用
route
装饰器的
methods
参数设置即可(当然是你首先要实现这个方法)
![508489-20180510191634922-1049823259.png](https://i-blog.csdnimg.cn/blog_migrate/e6259b3525f3d301f24d8eab8330ac64.png)
注意这里的表述,是在路由之上,新添加出来的一块。
为了达到统一、高质量的界面,我们需要使用模板,比如默认的这个
![Logo](https://i-blog.csdnimg.cn/blog_migrate/1c855baa9e44ba2af9c0bb1258a7939d.png)
Flask会自动配置Jinja 模板,所以我们不需要其他配置了。默认情况下,模板文件需要放在
templates
文件夹下。(这里的模板文件应该在之前的模板上面增加的)
想要好看的模板,最终需要的还是js和css
![508489-20180510191635377-1018014519.png](https://i-blog.csdnimg.cn/blog_migrate/598efa8f0a81263b1480aaea4e94f018.png)
我们可以得到这样的结果:
![508489-20180510191635650-896869044.png](https://i-blog.csdnimg.cn/blog_migrate/bf82a47b1cdf1a1cf863227569fd501a.png)
直接一行代码调用过去。
![508489-20180510191635887-11957076.png](https://i-blog.csdnimg.cn/blog_migrate/66d8aa41b3734e25575d56de38043f73.png)
代码块需要包含在
{% %}
块中
双大括号中的内容不会被转义,所有内容都会原样输出,它常常和其他辅助函数一起使用。下面是一个例子
<a
class=
"navbar-brand" href={{ url_for(
'index') }}>Flask小例子</a>
外引文件,使用
{%
extends
'layout.html' %}方法
{% extends
'layout.html' %}
{% %}
中也可以写Python代码
<div
class=metanav>
{%
if
not session.logged_in %}
<a href=
"
{{
url_for('login')
}}
">log
in</a>
{%
else %}
<a href=
"
{{
url_for('logout')
}}
">log out</a>
{% endif %}
</div>
循环
<tbody>
{%
for key,value
in data.items() %}
<tr>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
{% endfor %}
<tr>
<td>文件</td>
<td></td>
</tr>
</tbody>
注意,字体产生了变化
![508489-20180510191636249-429580692.png](https://i-blog.csdnimg.cn/blog_migrate/be0acb4104ac1c571c4ac66ac31f539a.png)
Request 对象是一个全局对象,利用它的属性和方法,我们可以方便的获取从页面传递过来的参数
![508489-20180510191636491-1910157985.png](https://i-blog.csdnimg.cn/blog_migrate/c3ae35a2208dee8e1701b3abc1327903.png)
可以用来判明数据来源。
文件上传是肯定需要解决的问题,
利用Flask也可以方便的获取表单中上传的文件,只需要利用 request 的
files
属性即可。
利用
werkzeug
提供的
secure_filename
方法来获取安全的文件名。
@app.route(
'/upload',
methods=[
'GET',
'POST'])
def
upload_file():
if request.method ==
'POST':
f = request.files[
'the_file']
f.save(
'/var/www/uploads/' + secure_filename(f.filename))
不仅仅是这样,肯定还需要更多的要素。
二、解决关键问题
传统方法(当然传统的也是非常好的)只有三个步骤:
1、创建一个上传表单:
<form method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Upload"></form>
2、当按下提交键后,通过request对象上的files获取文件。和以前用request获取表单值一样,使用input字段的name值获取:
file = request.files['file']
3、使用save()方法保存文件,指定保存的地址及文件名:
file.save(path + filename)
這里有一个完整的实现,并且是可用的
# -*- coding: utf-8 -*-
import os
from flask import Flask, request, url_for, send_from_directory
from werkzeug import secure_filename
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.getcwd()
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
html = '''
<!DOCTYPE html>
<title>Upload File</title>
<h1>图片上传</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=上传>
</form>
'''
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
file_url = url_for('uploaded_file', filename=filename)
return html + '<br><img src=' + file_url + '>'
return html
if __name__ == '__main__':
app.run()
我看可以这样来理解使用:
1、不管python语言有多少,
html =
'''
<!DOCTYPE html>
<title>Upload File</title>
<h1>图片上传</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=上传>
</form>
'''
都是html主体,这样写应该是不需要套模板的;
2、显而易见,submit动作,触发
@app.route
(
'/'
,
methods
=
[
'GET'
,
'POST'
])
而这个时候,能够验证数据是否已经上传上去。注意最后
return html + '<br><img src=' + file_url + '>'
这样直接返回结果,当然你可以进行大小控制,也可以使用css
3、
file_url
=
url_for(
'uploaded_file'
,
filename
=
filename)
用来构建url,对应的就是
uploaded_file
(
filename
):
4、
在 Flask 0.5以上的版本我们可以使用一个函数来实现此功能:
from
flask
import
send_from_directory
@app.route ( '/uploads/<filename>' ) def uploaded_file ( filename ):
return send_from_directory ( app . config [ 'UPLOAD_FOLDER' ], filename )
@app.route ( '/uploads/<filename>' ) def uploaded_file ( filename ):
return send_from_directory ( app . config [ 'UPLOAD_FOLDER' ], filename )
用以提供对以及那个上传数据的访问。
3、进一步读懂现有代码,现有代码中的结果是如何传递的?
数据上传这块,现有代码调用了模板
return render_template(
'index.html')
同时使用了css和js,但是没有脱离本质,还是先上传到内存中,然后去读取。和model的交互,在predict这里:
使用了js进行调用,还有fadein的效果,高大上
![508489-20180510191637000-298220782.png](https://i-blog.csdnimg.cn/blog_migrate/1472fd0bc4cc055326186a636896167f.png)
对应
![508489-20180510191637302-681549265.png](https://i-blog.csdnimg.cn/blog_migrate/1c56e06539caa5130ca740050c1f9165.png)
首先是获得文件,然后是将其进行保存,然后是调用已经建立好的模型进行predict,返回的是一个argmax,类似于onehot的值。
在这个过程中,生成的是string数据,然后就是想办法显示出来。并没有所谓json在里面,当然一个原因也是不需要。
在原始代码中,使用了
![508489-20180510191637594-1242491030.png](https://i-blog.csdnimg.cn/blog_migrate/2021ee2714cd79bb53fb8d7a04056c8b.png)
也就是imagenet自己的一个将onehot进行解码的程序。我这里为了CBIR进行了修改。
![508489-20180510191637850-1961705883.png](https://i-blog.csdnimg.cn/blog_migrate/3b3d5577237191ba47b0f2426b759d0b.png)
能够直接显示结果,后面还需要进一步优化,但是已经能够说明问题。
总的来说,还是onehot,或者数组,之类的东西。
这个地方和prsima还不一样。prisma肯定是生成图片的,可能是放在服务器上供下载的,而这里string类型的结果,确实可以直接显示、处理并调用的。
感谢阅读至此,希望有所帮助。
附件列表