Sub-directory 为 Flask 网络应用制作 in-memory 文件系统时出现问题
Sub-directory problem when making in-memory file system for Flask web app
我正在创建一个 virtual/in-memory 文件系统作为 Flask 应用程序的一部分,用户在其中创建文件和文件夹,我将它们保存在 SQL 数据库中并显示目录树回到 UI 中的用户(想想 dropbox/google 驱动器)。
为了 reprex,'File' 和 'Folder' SQL 表中的相关元数据为:['object_id', 'parent_id', 'child_nodes']
其中,
- object_id = 唯一标识符
- parent_id=sub-file或sub-folder属于
的parentobject_id
- child_nodes = child object_id parent
我创建了项目和文件 类 来处理内部方法和属性(排除但必需)。所以理想情况下,我的最终解决方案中需要 类。
我 运行 遇到的主要问题是将 sub-directories 作为 child_nodes
附加到目录。 这是可以观察到的 [在评论中从 dir_list[1]
迭代到 dir_list[2]
时,dir_list[1]
已经附加到 dir_list[0]
,因此不会反映以下迭代。
正在寻找有关如何实现它的任何建议。我也完全愿意完全使用不同的数据结构,只要我可以添加元数据并按照与 FileDir.create_tree()
相同的方式对其进行格式化。 注意:我需要遍历理论上无限的数字子目录,而不仅仅是我的 reprex 中的内容。
# Objects for organizing each struct -----
class File():
def __init__(self, file_list):
self.id = file_list[0]
self.name = file_list[1]
self.parent = file_list[2]
self.directory = False
class Directory:
def __init__(self, dir_list):
self.id = dir_list [0]
self.name = dir_list [1]
self.parent = dir_list [2]
self.child_nodes = []
self.directory = True
def add_file_node(self, node):
node = {
'id': node.id,
'name': node.name,
'parent': self.parent,
'is_dir': node.directory
}
self.child_nodes.append(node)
def add_dir_node(self, node):
node = {
'id': node.id,
'name': node.name,
'parent': self.parent,
'is_dir': node.directory,
'children': self.child_nodes
}
self.child_nodes.append(node)
def return_tree(self):
tree = {
'name': self.name,
'children': self.child_nodes,
'parent': self.parent,
'is_directory': self.directory
}
return tree
class FileDir():
def __init__(self, dir_list):
self.dir_list = dir_list
def create_tree(self):
tree = []
for directory in self.dir_list:
tree.append(directory.return_tree())
return tree
# Example Data (formatted as 2d-list from my SQL query) -----
dir_list = [
['10001', 'dir_1', None],
['10002', 'dir_2', '10001'],
['10003', 'dir_3', '10002'],
['10004', 'dir_4', None]
]
file_list = [
['21110', 'file1.csv', None],
['21111', 'file2.csv', '10001'],
['21112', 'file3.csv', '10002'],
['21113', 'file3.csv', '10003']
]
dir_objs = [Directory(d) for d in dir_list]
file_objs = [File(f) for f in file_list]
for fil in file_objs:
if fil.parent:
for i, x in enumerate(dir_objs):
if fil.parent == x.id:
x.add_file_node(fil)
# TODO Append sub_folders
# ...
#
# for d in dir_objs:
# if d.parent:
# for i, x in enumerate(dir_objs):
# if d.parent == x.id:
# x.add_dir_node(d)
# dir_objs.remove(d)
tree = FileDir(dir_objs)
tree.create_tree()
这段代码能满足您的需求吗?
# Objects for organizing each struct -----
class File:
def __init__(self, file_list):
self.id = file_list[0]
self.name = file_list[1]
self.parent = file_list[2]
self.directory = False
class Directory:
def __init__(self, dir_list):
self.id = dir_list[0]
self.name = dir_list[1]
self.parent = dir_list[2]
self.child_nodes = []
self.directory = True
def add_file_node(self, node):
node = {
'id': node.id,
'name': node.name,
'parent': self.parent,
'is_dir': node.directory
}
self.child_nodes.append(node)
def add_dir_node(self, node):
node = {
'id': node.id,
'name': node.name,
'parent': self.parent,
'is_dir': node.directory,
'children': self.child_nodes
}
self.child_nodes.append(node)
def return_tree(self):
tree = {
'name': self.name,
'children': self.child_nodes,
'parent': self.parent,
'is_directory': self.directory
}
return tree
class FileDir:
def __init__(self, dir_list):
self.dir_list = dir_list
def create_tree(self):
tree = []
for directory in self.dir_list:
tree.append(directory.return_tree())
return tree
# Example Data (formatted as 2d-list from my SQL query) -----
dir_list = [
['10001', 'dir_1', None],
['10002', 'dir_2', '10001'],
['10003', 'dir_3', '10002'],
['10004', 'dir_4', None]
]
file_list = [
['21110', 'file1.csv', None],
['21111', 'file2.csv', '10001'],
['21112', 'file3.csv', '10002'],
['21113', 'file3.csv', '10003']
]
dir_objs = [Directory(d) for d in dir_list]
file_objs = [File(f) for f in file_list]
for fil in file_objs:
if fil.parent:
for i, x in enumerate(dir_objs):
if fil.parent == x.id:
x.add_file_node(fil)
for dir_obj in dir_objs:
if dir_obj.parent:
for potential_parent_dir_obj in dir_objs:
if dir_obj.parent == potential_parent_dir_obj.id:
potential_parent_dir_obj.add_dir_node(dir_obj)
dir_objs = [dir_obj for dir_obj in dir_objs if not dir_obj.parent]
tree = FileDir(dir_objs)
tree.create_tree()
这不会处理深度超过两层的目录树,但您的示例数据并未表明这是必要的。如果您确实需要处理深层嵌套的层次结构,请告诉我。您将需要一种不同的方法。
编辑
这是我使用 Python 3.8 开发的更强大的版本,可以处理任意深度。我还没有对其进行广泛的测试,但希望这会有所帮助。没有令人困惑的递归(表面上)。
from __future__ import annotations
from typing import Union, List
from dataclasses import dataclass, asdict, field
import json
@dataclass
class Node:
node_id: str
name: str
parent_node_id: str = None
def to_tree(self):
return asdict(self)
@dataclass
class File(Node):
is_directory: bool = False
@dataclass
class Directory(Node):
is_directory: bool = True
children: List[Union[Directory, File]] = field(default_factory=list)
def add_child(self, child: Union[Directory, File]):
self.children.append(child)
class FileSystem:
def __init__(self, *nodes):
self.nodes = {node.node_id: node for node in nodes}
for node in self.non_root_nodes:
self.nodes[node.parent_node_id].add_child(node)
def __getitem__(self, node_id):
return self.nodes[node_id]
@property
def root_nodes(self):
return [node for node in self.nodes.values() if node.parent_node_id is None]
@property
def non_root_nodes(self):
return [node for node in self.nodes.values() if node.parent_node_id is not None]
@property
def directories(self):
return [node for node in self.nodes.values() if node.is_directory]
@property
def files(self):
return [node for node in self.nodes.values() if not node.is_directory]
def to_tree(self):
return [node.to_tree() for node in self.root_nodes]
dir_list = [
# id, name, parent_node_id
['10001', 'dir_1', None],
['10002', 'dir_2', '10001'],
['10003', 'dir_3', '10002'],
['10004', 'dir_4', None]
]
file_list = [
['21110', 'file1.csv', None],
['21111', 'file2.csv', '10001'],
['21112', 'file3.csv', '10002'],
['21113', 'file3.csv', '10003']
]
dir_list = [Directory(*directory) for directory in dir_list]
file_list = [File(*file) for file in file_list]
file_system = FileSystem(*dir_list, *file_list)
tree = file_system.to_tree()
print(json.dumps(tree, indent=2))
我正在创建一个 virtual/in-memory 文件系统作为 Flask 应用程序的一部分,用户在其中创建文件和文件夹,我将它们保存在 SQL 数据库中并显示目录树回到 UI 中的用户(想想 dropbox/google 驱动器)。
为了 reprex,'File' 和 'Folder' SQL 表中的相关元数据为:['object_id', 'parent_id', 'child_nodes']
其中,
- object_id = 唯一标识符
- parent_id=sub-file或sub-folder属于 的parentobject_id
- child_nodes = child object_id parent
我创建了项目和文件 类 来处理内部方法和属性(排除但必需)。所以理想情况下,我的最终解决方案中需要 类。
我 运行 遇到的主要问题是将 sub-directories 作为 child_nodes
附加到目录。 这是可以观察到的 [在评论中从 dir_list[1]
迭代到 dir_list[2]
时,dir_list[1]
已经附加到 dir_list[0]
,因此不会反映以下迭代。
正在寻找有关如何实现它的任何建议。我也完全愿意完全使用不同的数据结构,只要我可以添加元数据并按照与 FileDir.create_tree()
相同的方式对其进行格式化。 注意:我需要遍历理论上无限的数字子目录,而不仅仅是我的 reprex 中的内容。
# Objects for organizing each struct -----
class File():
def __init__(self, file_list):
self.id = file_list[0]
self.name = file_list[1]
self.parent = file_list[2]
self.directory = False
class Directory:
def __init__(self, dir_list):
self.id = dir_list [0]
self.name = dir_list [1]
self.parent = dir_list [2]
self.child_nodes = []
self.directory = True
def add_file_node(self, node):
node = {
'id': node.id,
'name': node.name,
'parent': self.parent,
'is_dir': node.directory
}
self.child_nodes.append(node)
def add_dir_node(self, node):
node = {
'id': node.id,
'name': node.name,
'parent': self.parent,
'is_dir': node.directory,
'children': self.child_nodes
}
self.child_nodes.append(node)
def return_tree(self):
tree = {
'name': self.name,
'children': self.child_nodes,
'parent': self.parent,
'is_directory': self.directory
}
return tree
class FileDir():
def __init__(self, dir_list):
self.dir_list = dir_list
def create_tree(self):
tree = []
for directory in self.dir_list:
tree.append(directory.return_tree())
return tree
# Example Data (formatted as 2d-list from my SQL query) -----
dir_list = [
['10001', 'dir_1', None],
['10002', 'dir_2', '10001'],
['10003', 'dir_3', '10002'],
['10004', 'dir_4', None]
]
file_list = [
['21110', 'file1.csv', None],
['21111', 'file2.csv', '10001'],
['21112', 'file3.csv', '10002'],
['21113', 'file3.csv', '10003']
]
dir_objs = [Directory(d) for d in dir_list]
file_objs = [File(f) for f in file_list]
for fil in file_objs:
if fil.parent:
for i, x in enumerate(dir_objs):
if fil.parent == x.id:
x.add_file_node(fil)
# TODO Append sub_folders
# ...
#
# for d in dir_objs:
# if d.parent:
# for i, x in enumerate(dir_objs):
# if d.parent == x.id:
# x.add_dir_node(d)
# dir_objs.remove(d)
tree = FileDir(dir_objs)
tree.create_tree()
这段代码能满足您的需求吗?
# Objects for organizing each struct -----
class File:
def __init__(self, file_list):
self.id = file_list[0]
self.name = file_list[1]
self.parent = file_list[2]
self.directory = False
class Directory:
def __init__(self, dir_list):
self.id = dir_list[0]
self.name = dir_list[1]
self.parent = dir_list[2]
self.child_nodes = []
self.directory = True
def add_file_node(self, node):
node = {
'id': node.id,
'name': node.name,
'parent': self.parent,
'is_dir': node.directory
}
self.child_nodes.append(node)
def add_dir_node(self, node):
node = {
'id': node.id,
'name': node.name,
'parent': self.parent,
'is_dir': node.directory,
'children': self.child_nodes
}
self.child_nodes.append(node)
def return_tree(self):
tree = {
'name': self.name,
'children': self.child_nodes,
'parent': self.parent,
'is_directory': self.directory
}
return tree
class FileDir:
def __init__(self, dir_list):
self.dir_list = dir_list
def create_tree(self):
tree = []
for directory in self.dir_list:
tree.append(directory.return_tree())
return tree
# Example Data (formatted as 2d-list from my SQL query) -----
dir_list = [
['10001', 'dir_1', None],
['10002', 'dir_2', '10001'],
['10003', 'dir_3', '10002'],
['10004', 'dir_4', None]
]
file_list = [
['21110', 'file1.csv', None],
['21111', 'file2.csv', '10001'],
['21112', 'file3.csv', '10002'],
['21113', 'file3.csv', '10003']
]
dir_objs = [Directory(d) for d in dir_list]
file_objs = [File(f) for f in file_list]
for fil in file_objs:
if fil.parent:
for i, x in enumerate(dir_objs):
if fil.parent == x.id:
x.add_file_node(fil)
for dir_obj in dir_objs:
if dir_obj.parent:
for potential_parent_dir_obj in dir_objs:
if dir_obj.parent == potential_parent_dir_obj.id:
potential_parent_dir_obj.add_dir_node(dir_obj)
dir_objs = [dir_obj for dir_obj in dir_objs if not dir_obj.parent]
tree = FileDir(dir_objs)
tree.create_tree()
这不会处理深度超过两层的目录树,但您的示例数据并未表明这是必要的。如果您确实需要处理深层嵌套的层次结构,请告诉我。您将需要一种不同的方法。
编辑
这是我使用 Python 3.8 开发的更强大的版本,可以处理任意深度。我还没有对其进行广泛的测试,但希望这会有所帮助。没有令人困惑的递归(表面上)。
from __future__ import annotations
from typing import Union, List
from dataclasses import dataclass, asdict, field
import json
@dataclass
class Node:
node_id: str
name: str
parent_node_id: str = None
def to_tree(self):
return asdict(self)
@dataclass
class File(Node):
is_directory: bool = False
@dataclass
class Directory(Node):
is_directory: bool = True
children: List[Union[Directory, File]] = field(default_factory=list)
def add_child(self, child: Union[Directory, File]):
self.children.append(child)
class FileSystem:
def __init__(self, *nodes):
self.nodes = {node.node_id: node for node in nodes}
for node in self.non_root_nodes:
self.nodes[node.parent_node_id].add_child(node)
def __getitem__(self, node_id):
return self.nodes[node_id]
@property
def root_nodes(self):
return [node for node in self.nodes.values() if node.parent_node_id is None]
@property
def non_root_nodes(self):
return [node for node in self.nodes.values() if node.parent_node_id is not None]
@property
def directories(self):
return [node for node in self.nodes.values() if node.is_directory]
@property
def files(self):
return [node for node in self.nodes.values() if not node.is_directory]
def to_tree(self):
return [node.to_tree() for node in self.root_nodes]
dir_list = [
# id, name, parent_node_id
['10001', 'dir_1', None],
['10002', 'dir_2', '10001'],
['10003', 'dir_3', '10002'],
['10004', 'dir_4', None]
]
file_list = [
['21110', 'file1.csv', None],
['21111', 'file2.csv', '10001'],
['21112', 'file3.csv', '10002'],
['21113', 'file3.csv', '10003']
]
dir_list = [Directory(*directory) for directory in dir_list]
file_list = [File(*file) for file in file_list]
file_system = FileSystem(*dir_list, *file_list)
tree = file_system.to_tree()
print(json.dumps(tree, indent=2))