Skip to content

Commit dd4c76e

Browse files
author
mominur-helios
committed
add file manager
1 parent 59939e8 commit dd4c76e

File tree

12 files changed

+266
-3
lines changed

12 files changed

+266
-3
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ env
1414

1515
.env
1616
yarn.lock
17+
18+
/media

core/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@
158158
os.path.join(BASE_DIR, 'static'),
159159
)
160160

161+
MEDIA_URL = '/media/'
162+
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
163+
161164
#if not DEBUG:
162165
# STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
163166

core/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
"""
1616
from django.contrib import admin
1717
from django.urls import include, path
18+
from django.conf import settings
19+
from django.conf.urls.static import static
1820

1921
urlpatterns = [
2022
path('', include('home.urls')),
2123
path("admin/", admin.site.urls),
2224
path("", include('admin_corporate.urls'))
23-
]
25+
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

home/templatetags/__init__.py

Whitespace-only changes.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from django import template
2+
import os
3+
from urllib.parse import quote
4+
5+
register = template.Library()
6+
7+
@register.filter
8+
def file_extension(value):
9+
_, extension = os.path.splitext(value)
10+
return extension.lower()
11+
12+
13+
@register.filter
14+
def encoded_file_path(path):
15+
return path.replace('/', '%slash%')

home/urls.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@
44

55
urlpatterns = [
66
path('', views.index, name='index'),
7+
path('file-manager/', views.file_manager, name='file-manager'),
8+
path('delete-file/<str:file_path>/', views.delete_file, name='delete_file'),
9+
path('download-file/<str:file_path>/', views.download_file, name='download_file'),
10+
path('upload-file/', views.upload_file, name='upload_file'),
711
]

home/views.py

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
from django.shortcuts import render
2-
from django.http import HttpResponse
1+
import os
2+
from django.shortcuts import render, redirect
3+
from django.http import HttpResponse, FileResponse, Http404
4+
from django.conf import settings
35

46
# Create your views here.
57

@@ -12,3 +14,78 @@ def index(request):
1214

1315
# Page from the theme
1416
return render(request, 'pages/dashboard.html', context=context)
17+
18+
def get_files_from_directory(directory_path):
19+
files = []
20+
for root, _, filenames in os.walk(directory_path):
21+
for filename in filenames:
22+
file_path = os.path.join(root, filename)
23+
files.append({
24+
'file': file_path.split('/media/')[1],
25+
'filename': filename,
26+
'file_path': file_path
27+
})
28+
return files
29+
30+
31+
def file_manager(request):
32+
media_path = os.path.join(settings.MEDIA_ROOT)
33+
directories = generate_nested_directory(media_path, media_path)
34+
selected_directory = request.GET.get('directory', '')
35+
36+
files = []
37+
if selected_directory:
38+
selected_directory_path = os.path.join(media_path, selected_directory)
39+
if os.path.isdir(selected_directory_path):
40+
files = get_files_from_directory(selected_directory_path)
41+
42+
context = {
43+
'directories': directories,
44+
'files': files,
45+
'selected_directory': selected_directory,
46+
'segment': 'file_manager',
47+
'MEDIA_ROOT': settings.MEDIA_ROOT
48+
}
49+
return render(request, 'pages/file-manager.html', context)
50+
51+
52+
def generate_nested_directory(root_path, current_path):
53+
directories = []
54+
for name in os.listdir(current_path):
55+
if os.path.isdir(os.path.join(current_path, name)):
56+
nested_path = os.path.join(current_path, name)
57+
nested_directories = generate_nested_directory(root_path, nested_path)
58+
directories.append({'name': name, 'path': os.path.relpath(nested_path, root_path), 'directories': nested_directories})
59+
return directories
60+
61+
62+
def delete_file(request, file_path):
63+
path = file_path.replace('%slash%', '/')
64+
absolute_file_path = os.path.join(settings.MEDIA_ROOT, path)
65+
os.remove(absolute_file_path)
66+
print("File deleted", absolute_file_path)
67+
return redirect(request.META.get('HTTP_REFERER'))
68+
69+
70+
def download_file(request, file_path):
71+
path = file_path.replace('%slash%', '/')
72+
absolute_file_path = os.path.join(settings.MEDIA_ROOT, path)
73+
if os.path.exists(absolute_file_path):
74+
with open(absolute_file_path, 'rb') as fh:
75+
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
76+
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(absolute_file_path)
77+
return response
78+
raise Http404
79+
80+
def upload_file(request):
81+
media_path = os.path.join(settings.MEDIA_ROOT)
82+
selected_directory = request.POST.get('directory', '')
83+
selected_directory_path = os.path.join(media_path, selected_directory)
84+
if request.method == 'POST':
85+
file = request.FILES.get('file')
86+
file_path = os.path.join(selected_directory_path, file.name)
87+
with open(file_path, 'wb') as destination:
88+
for chunk in file.chunks():
89+
destination.write(chunk)
90+
91+
return redirect(request.META.get('HTTP_REFERER'))

static/js/plugins/font-awesome.min.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

templates/includes/sidebar.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,22 @@
130130
<span class="nav-link-text ms-1">Wallet</span>
131131
</a>
132132
</li>
133+
<li class="nav-item">
134+
<a class="nav-link {% if 'wallet' in segment %}active{% endif %}" href="{% url 'file-manager' %}">
135+
<div class="icon icon-shape icon-sm px-0 text-center d-flex align-items-center justify-content-center">
136+
<svg width="30px" height="30px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
137+
<title>wallet</title>
138+
<g id="wallet" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
139+
<g id="credit-card" transform="translate(12.000000, 15.000000)" fill="#FFFFFF">
140+
<path class="color-background" d="M3,0 C1.343145,0 0,1.343145 0,3 L0,4.5 L24,4.5 L24,3 C24,1.343145 22.6569,0 21,0 L3,0 Z" id="Path" fill-rule="nonzero"></path>
141+
<path class="color-foreground" d="M24,7.5 L0,7.5 L0,15 C0,16.6569 1.343145,18 3,18 L21,18 C22.6569,18 24,16.6569 24,15 L24,7.5 Z M3,13.5 C3,12.67155 3.67158,12 4.5,12 L6,12 C6.82842,12 7.5,12.67155 7.5,13.5 C7.5,14.32845 6.82842,15 6,15 L4.5,15 C3.67158,15 3,14.32845 3,13.5 Z M10.5,12 C9.67158,12 9,12.67155 9,13.5 C9,14.32845 9.67158,15 10.5,15 L12,15 C12.82845,15 13.5,14.32845 13.5,13.5 C13.5,12.67155 12.82845,12 12,12 L10.5,12 Z" id="Shape"></path>
142+
</g>
143+
</g>
144+
</svg>
145+
</div>
146+
<span class="nav-link-text ms-1">File Manager</span>
147+
</a>
148+
</li>
133149
<li class="nav-item">
134150
<a class="nav-link {% if 'rtl' in segment %}active{% endif %} " href="{% url 'rtl' %}">
135151
<div class="icon icon-shape icon-sm px-0 text-center d-flex align-items-center justify-content-center">
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{% for subdirectory in directory.directories %}
2+
{% if subdirectory.directories %}
3+
<li
4+
id="collapse{{directory.name}}"
5+
class="ms-{{depth}} collapse {% if subdirectory.name in request.get_full_path %} show {% endif %}"
6+
>
7+
<i class="fa-solid fa-folder"></i>
8+
<a
9+
data-bs-toggle="collapse"
10+
href="#collapse{{subdirectory.name}}"
11+
role="button"
12+
aria-expanded="false"
13+
aria-controls="collapse{{subdirectory.name}}"
14+
>
15+
{{ subdirectory.name }}
16+
</a>
17+
</li>
18+
{% include 'includes/subdirectories.html' with directory=subdirectory depth=depth|add:"2" %}
19+
{% else %}
20+
<li
21+
id="collapse{{directory.name}}"
22+
class="ms-{{depth}} collapse {% if subdirectory.name in request.get_full_path %} show {% endif %} "
23+
>
24+
<i class="fa-solid fa-folder"></i>
25+
<a href="?directory={{subdirectory.path}}">{{ subdirectory.name }}</a>
26+
</li>
27+
{% endif %}
28+
{% endfor %}

0 commit comments

Comments
 (0)