我用一个页面显示一个文件夹下面的所有文件, 页面上有上传和删除的方法,
上传的方法 ok, 主要就是提交之后, 使用 redirect, 这个时候新上传的文件会直接显示出来,
return redirect(url_for('show_user_file', username=session['cur_username']))
但是问题出现在删除的时候, 使用的代码依然是, return redirect(url_for('show_user_file', username=session['cur_username']))
但是这个时候文件不会减少, 就是虽然删除了, 文件还是显示在页面上.
我调试了一下, show_user_filereturn render_template('listfile.html', files=file_dict, used_space = used_space)
的参数里面, file_dict 是存储当前文件夹里面的文件的参数, 这个 file_dict 的内容是 ok 的, 也就是说这里面已经没有了那个被删除的文件, 但是页面上还有, 只有刷新一下这个删除的文件才会删除掉。
开始想在页面的里面直接用 JavaScript 删除掉这个文件, 但是也可能出现服务端删除失败的情况, 所以不想用这个方法。
请问这个问题如何解决, 删除文件后为什么 render 之后的页面没有更新?
我开始猜测是 post 之后更新页面, 但是不是修改了之后还是没有变请问是怎么回事?
删除:
@app.route('/delfile', methods=['GET', 'POST'])
def delfile():
print('in delfile')
if request.method == 'GET':
filename = re.sub("_btn$", "", request.args.get('filename'))
file_path = os.path.join(session['cur_username'], filename)
if os.path.exists(file_path):
os.remove(file_path)
return redirect(url_for('show_user_file', username=session['cur_username']))
上传
@app.route('/upload/<username>', methods=['GET', 'POST'])
def show_user_file(username):
file_path = username
if not os.path.exists(file_path):
os.makedirs(file_path)
BASE_DIR = '.'
req_path = username
# Joining the base and the requested path
abs_path = os.path.join(BASE_DIR, req_path)
# Return 404 if path doesn't exist
if not os.path.exists(abs_path):
return abort(404)
# Check if path is a file and serve
if os.path.isfile(abs_path):
return send_file(abs_path)
if request.method == 'POST':
file = request.files['file']
if file:
# filename = secure_filename(file.filename)
filename = file.filename
file.save(os.path.join(file_path, filename))
return redirect(url_for('show_user_file', username=session['cur_username']))
files = os.listdir(abs_path)
file_dict={}
for i in files:
file_dict[i] = os.path.join(abs_path, i)
used_space = get_size(abs_path)
return render_template('listfile.html', files=file_dict, used_space = used_space)
show_user_file:
# Show User Folder
@app.route('/upload/<username>', methods=['GET', 'POST'])
def show_user_file(username):
file_path = username
if not os.path.exists(file_path):
os.makedirs(file_path)
BASE_DIR = '.'
req_path = username
# Joining the base and the requested path
abs_path = os.path.join(BASE_DIR, req_path)
# Return 404 if path doesn't exist
if not os.path.exists(abs_path):
return abort(404)
# Check if path is a file and serve
if os.path.isfile(abs_path):
return send_file(abs_path)
if request.method == 'POST':
file = request.files['file']
if file:
# filename = secure_filename(file.filename)
filename = file.filename
file.save(os.path.join(file_path, filename))
return redirect(url_for('show_user_file', username=session['cur_username']))
files = os.listdir(abs_path)
file_dict={}
for i in files:
file_dict[i] = os.path.join(abs_path, i)
used_space = get_size(abs_path)
return render_template('listfile.html', files=file_dict, used_space = used_space)
1
justinwu 2018-03-14 21:34:49 +08:00 1
啥原因我也不知道,但是先说说你设计上的一些问题,路子走对了,再调问题吧:
一般都是 Post/Redirect/Get 模式,你删除文件却是 Get/Redirect/Get 模式。对服务端数据有修改的操作请不要用 GET。你那个 delfile 就该用 POST。 你的 show_user_file action 怎么对应的又是 /upload url,怪怪的。 下面这样才对头啊,各函数各司其职: @app.route('/delfile', methods=['POST']) def delfile(): @app.route('/upload/<username>', methods=['POST']) def upload_file(username): @app.route('/listfiles/<username>', methods=['GET']) def show_user_file(username): 另外,url 里面不要搞 username 吧,你难道要一个用户操作另一个用户的文件?如果不是,默默用 session 里面的就完了。 |
2
geek123 2018-03-14 21:43:57 +08:00 1
重定向响应
使用 flask 框架的 redirect()方法,可以要求客户端进行重定向: flask.redirect(location, code=302, Response=None) redirect()方法其实是构造了一个具有重定向状态码的 Response 对象。重定向状态码 默认为 302,这表示一个临时性重定向。redirect()方法还支持以下重定向状态码: 301 - 请求的网页已被永久移动到新位置 302 - 服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 303 - 对于 POST 请求,它表示请求已经被处理,客户端可以接着使用 GET 方法去请求 Location 里的 URI 305 - 请求者只能使用代理访问请求的网页。 307 - 对于 POST 请求,表示请求还没有被处理,客户端应该向 Location 里的 URI 重新发起 POST 请求 你指定一下重定向码试试 |
3
woshichuanqilz OP @justinwu 非常感谢详尽的回答, 十分感谢, 受益匪浅。
1. delfile 中的 post 已经修改 2. 函数名和 url 的匹配已经修改 ``` #del file @app.route('/delfile', methods=['GET', 'POST']) def delfile(): print('in delfile') if 'logged_in' not in session or not session['logged_in']: return '用户未登录或者访问权限不够' if request.method == 'POST': # filename = re.sub("_btn$", "", request.args.get('filename')) filename = re.sub("_btn$", "", request.form['filename']) file_path = os.path.join(session['cur_username'], filename) if os.path.exists(file_path): os.remove(file_path) file_dict, used_space = get_file_info(session['cur_username']) return render_template('listfile.html', files=file_dict, used_space = used_space) ``` ``` @app.route('/show_user_file', methods=['GET', 'POST']) def show_user_file(): if 'logged_in' not in session or not session['logged_in']: return '用户未登录或者访问权限不够' file_path = session['cur_username'] username = session['cur_username'] if not os.path.exists(file_path): os.makedirs(file_path) if request.method == 'POST': file = request.files['file'] if file: # filename = secure_filename(file.filename) filename = file.filename file.save(os.path.join(file_path, filename)) return redirect(url_for('show_user_file')) file_dict, used_space = get_file_info(username) return render_template('listfile.html', files=file_dict, used_space = used_space) ``` ``` def get_file_info(username): BASE_DIR = '.' req_path = username file_path = username # Joining the base and the requested path abs_path = os.path.join(BASE_DIR, req_path) # Return 404 if path doesn't exist if not os.path.exists(abs_path): return abort(404) # Check if path is a file and serve if os.path.isfile(abs_path): return send_file(abs_path) files = os.listdir(abs_path) file_dict={} for i in files: file_dict[i] = os.path.join(abs_path, i) used_space = get_size(abs_path) return file_dict, used_space ``` ![20180315100643]( http://7xpvdr.com1.z0.glb.clouddn.com/680c2fc1-aab5-4f11-bb3b-28b772d229cb0315100557.png) 这个是我的实操的效果图, 点击删除按钮, file_dict 已经变成空了, 但是 render_template 的网页没有刷新 ![20180315104614]( http://7xpvdr.com1.z0.glb.clouddn.com/ea205440-58b0-4024-80d3-990ca41057ce0315104524.png) |
4
woshichuanqilz OP @geek123 研究了一下没太看懂这些状态码, 那个能适用于我现在的这个情况。 谢谢~
|
5
woshichuanqilz OP ```
@app.route('/delfile', methods=['GET', 'POST']) def delfile(): print('in delfile') if 'logged_in' not in session or not session['logged_in']: return '用户未登录或者访问权限不够' if request.method == 'POST': # filename = re.sub("_btn$", "", request.args.get('filename')) filename = re.sub("_btn$", "", request.form['filename']) file_path = os.path.join(session['cur_username'], filename) if os.path.exists(file_path): os.remove(file_path) file_dict, used_space = get_file_info(session['cur_username']) print('file_dict:') print(file_dict) return redirect(url_for('show_user_file')) ``` delfile 修改成返回 redirect 还是不行。 |
6
justinwu 2018-03-15 11:07:53 +08:00 via iPhone 1
@woshichuanqilz 不用在 delfile 里面打印 file list dict,应该在 show user file 里面,看看 redirect 后请求到底来了没,状态到底对不对
|
7
woshichuanqilz OP @justinwu show_use file 里面也是空的
我看了一下源代码, 源代码是没有问题的, 就是说如果你点击删除之后, 查看源代码确实是对的已经更新了, 但是表现在页面上没有更新。 |
8
justinwu 2018-03-15 11:58:36 +08:00 via iPhone 1
@woshichuanqilz
打 server 请求 log 都打开,看看 del file 后有没有请求文件列表页面; 换不同浏览器试试看; chrome 开发者工具 network 调试;看看浏览器请求对不对; redirect 强制加一个 query string,搞点随机数时间戳都行,如 /listfile?hd23dd ; fiddler 工具分析整个 http 交互,看看有无异常; 顺藤摸瓜,总能找到哪里不对 |
9
woshichuanqilz OP @justinwu
1. 确定是请求了, 不然页面的源代码不会变化, 2. 换了火狐浏览器没有区别 3. chrome network 显示这个页面被请求过了 ![20180315141828]( http://7xpvdr.com1.z0.glb.clouddn.com/f3243b26-fa88-4962-a349-82c143fe23e70315141755.png) 4. 没明白那个 redirect 加参数是什么意思。 5. 用了 fiddler 确实很强大, 这里面是正常的删除文件后的页面已经返回了 ![20180315142044]( http://7xpvdr.com1.z0.glb.clouddn.com/b5b3ed71-7759-4913-8567-8f641b426b0b0315141925.png) 现在的问题是网页的源码都变了, 但是页面没有刷新。 我在 listfile 里面删除按钮绑定的是这个函数, 不知道处理有没有问题。 ``` <script> function sendfilename() { var xhttp = new XMLHttpRequest(); xhttp.open("POST", "/delfile", true); xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhttp.send("filename=" + event.target.id); } </script> ``` |
10
woshichuanqilz OP 在 chrome network 里面 disable cache 也没用。 我以为是缓存的问题
|
11
justinwu 2018-03-15 14:45:47 +08:00 2
@woshichuanqilz 你那个 sendfilename 的函数不对吧,只是发送请求,但是没有处理响应,没有让当前页面 refresh 或是 update 啊。
给一段我珍藏多年的表单 POST 代码,立马解决问题: <script> function post(path, params, method) { method = method || "post"; // Set method to post by default if not specified. // The rest of this code assumes you are not using a library. // It can be made less wordy if you use one. var form = document.createElement("form"); form.setAttribute("method", method); form.setAttribute("action", path); for(var key in params) { if(params.hasOwnProperty(key)) { var hiddenField = document.createElement("input"); hiddenField.setAttribute("type", "hidden"); hiddenField.setAttribute("name", key); hiddenField.setAttribute("value", params[key]); form.appendChild(hiddenField); } } document.body.appendChild(form); form.submit(); } //按钮 call 这个函数,跟据你上面的代码来的: function deleteFile(filename) { post("/delfile", { filename: filename }); } </script> |
12
woshichuanqilz OP 用一个 settimerout 在点击后 refresh 页面算是暂时解决了。。。 但是还是不知道原因。
|
13
woshichuanqilz OP @justinwu 这个 post 屌爆了。。。 真的是谢谢你的帮忙了
|