(45条消息) flask 读取文件夹文件,展示在页面,可以通过勾选删除_U盘失踪了的博客-CSDN博客
基本实现
针对上面的功能再优化
项目结构
app.py
import os
import shutil
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
def generate_file_tree(path):
root = {
'name': os.path.basename(path),
'type': 'directory',
'children': []
}
for item in os.listdir(path):
item_path = os.path.join(path, item)
if os.path.isdir(item_path):
child = generate_file_tree(item_path)
else:
child = {
'name': item,
'type': 'file'
}
root['children'].append(child)
return root
def delete_selected_files_and_dirs(path, file_tree):
selected_files = request.form.getlist('file-checkbox')
for item in file_tree['children']:
item_path = os.path.join(path, item['name'])
if item['type'] == 'file':
if item['name'] in selected_files:
os.remove(item_path)
elif item['type'] == 'directory':
if item['name'] in selected_files:
shutil.rmtree(item_path)
else:
delete_selected_files_and_dirs(item_path, item)
@app.route('/', methods=['GET', 'POST'])
def index():
if not os.path.isdir('testfile'):
os.makedirs('testfile')
file_tree = generate_file_tree('testfile')
if request.method == 'POST':
delete_selected_files_and_dirs('testfile', file_tree)
return redirect(url_for('index')) # 重定向到相同的URL
return render_template('index.html', file_tree=file_tree)
if __name__ == '__main__':
app.run()
templates / index.html
<!DOCTYPE html>
<html>
<head>
<title>File Manager</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 10px;
}
h1 {
text-align: center;
}
.file-tree {
list-style: none;
padding-left: 10px;
}
.file-tree .directory {
margin-bottom: 10px;
}
.file-tree .file {
list-style-type: none;
margin-left: -25px;
}
.checkbox-label {
display: inline-block;
margin-right: 2px;
}
.delete-button {
margin-top: 10px;
}
.file-tree li {
position: relative;
padding-left: 20px;
}
.file-tree li input[type="checkbox"] {
position: absolute;
right: 5; /* 将复选框放在右侧 */
top: 0;
}
</style>
</head>
<body>
<h1>File Manager</h1>
<form method="POST" action="{{ url_for('index') }}">
<ul class="file-tree">
{% for item in file_tree['children'] %}
{% if item['type'] == 'directory' %}
<li class="directory">
<label class="checkbox-label" for="{{ item['name'] }}"> {{ item['name'] }}</label>
<input type="checkbox" name="file-checkbox" value="{{ item['name'] }}" id="{{ item['name'] }}">
<ul>
{% for child in item['children'] %}
{% if child['type'] == 'file' %}
<li class="file">
<label class="checkbox-label" for="{{ child['name'] }}">{{ child['name'] }}</label>
<input type="checkbox" name="file-checkbox" value="{{ child['name'] }}" id="{{ child['name'] }}">
</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
<button type="submit" class="delete-button">Delete Selected Files</button>
</form>
</body>
</html>
效果图
优化一
目录折叠/展开文件
<!DOCTYPE html>
<html>
<head>
<title>File Manager</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
h1 {
text-align: center;
}
.file-tree {
list-style: none;
padding-left: 20px;
}
.file-tree .directory {
margin-bottom: 5px;
}
.file-tree .file {
list-style-type: none;
margin-left: 20px;
}
.checkbox-label {
display: flex;
align-items: center;
}
.checkbox-label input[type="checkbox"] {
margin-right: 5px;
}
.delete-button {
margin-top: 10px;
}
.file-tree li {
position: relative;
padding-left: 20px;
}
.file-tree .directory > .file-tree {
display: none;
}
.file-tree .directory.open > .file-tree {
display: block;
}
.file-tree .directory > .checkbox-label::before {
content: "+";
display: inline-block;
width: 10px;
text-align: center;
cursor: pointer;
}
.file-tree .directory.open > .checkbox-label::before {
content: "-";
}
/* 新增的样式 */
.file-tree .directory .checkbox-label {
position: relative;
left: -20px;
}
.file-tree .directory .checkbox-label input[type="checkbox"] {
margin-right: 5px;
}
.file-tree .directory:not(.open) .checkbox-label input[type="checkbox"] {
pointer-events: none;
}
</style>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
const directories = document.querySelectorAll('.directory');
directories.forEach(directory => {
const checkboxLabel = directory.querySelector('.checkbox-label');
const checkbox = directory.querySelector('input[type="checkbox"]');
checkbox.addEventListener('click', (event) => {
event.stopPropagation();
});
checkboxLabel.addEventListener('click', (event) => {
if (!event.target.matches('input[type="checkbox"]')) {
directory.classList.toggle('open');
if (!directory.classList.contains('open')) {
checkbox.checked = false;
}
}
});
directory.addEventListener('click', () => {
if (!directory.classList.contains('open')) {
checkbox.checked = false;
}
});
directory.addEventListener('transitionend', () => {
if (directory.classList.contains('open')) {
checkbox.disabled = false;
} else {
checkbox.disabled = true;
}
});
});
});
</script>
</head>
<body>
<h1>File Manager</h1>
<form method="POST" action="{{ url_for('index') }}">
<ul class="file-tree">
{% for item in file_tree['children'] %}
{% if item['type'] == 'directory' %}
<li class="directory">
<label class="checkbox-label">
<input type="checkbox" name="file-checkbox" value="{{ item['name'] }}" id="{{ item['name'] }}">
{{ item['name'] }}
</label>
<ul class="file-tree">
{% for child in item['children'] %}
{% if child['type'] == 'file' %}
<li class="file">
<label class="checkbox-label">
<input type="checkbox" name="file-checkbox" value="{{ child['name'] }}" id="{{ child['name'] }}">
{{ child['name'] }}
</label>
</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
<button type="submit" class="delete-button">Delete Selected Files</button>
</form>
</body>
</html>
优化二
隐藏目录的复选框
<!DOCTYPE html>
<html>
<head>
<title>File Manager</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
h1 {
text-align: center;
}
.file-tree {
list-style: none;
padding-left: 20px;
}
.file-tree .directory {
margin-bottom: 5px;
}
.file-tree .file {
list-style-type: none;
margin-left: 20px;
}
.delete-button {
margin-top: 10px;
}
.file-tree li {
position: relative;
padding-left: 20px;
}
.file-tree .directory > .file-tree {
display: none;
}
.file-tree .directory.open > .file-tree {
display: block;
}
.file-tree .directory > .checkbox-label::before {
content: "+";
display: inline-block;
width: 10px;
text-align: center;
cursor: pointer;
}
.file-tree .directory.open > .checkbox-label::before {
content: "-";
}
</style>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
const directories = document.querySelectorAll('.directory');
directories.forEach(directory => {
const checkboxLabel = directory.querySelector('.checkbox-label');
checkboxLabel.addEventListener('click', (event) => {
directory.classList.toggle('open');
event.stopPropagation();
});
directory.addEventListener('click', () => {
if (!directory.classList.contains('open')) {
directory.classList.add('open');
}
});
});
});
</script>
</head>
<body>
<h1>File Manager</h1>
<form method="POST" action="{{ url_for('index') }}">
<ul class="file-tree">
{% for item in file_tree['children'] %}
{% if item['type'] == 'directory' %}
<li class="directory">
<label class="checkbox-label">
{{ item['name'] }}
</label>
<ul class="file-tree">
{% for child in item['children'] %}
{% if child['type'] == 'file' %}
<li class="file">
<label class="checkbox-label">
<input type="checkbox" name="file-checkbox" value="{{ child['name'] }}" id="{{ child['name'] }}">
{{ child['name'] }}
</label>
</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
<button type="submit" class="delete-button">Delete Selected Files</button>
</form>
</body>
</html>