Added search function.

This commit is contained in:
2023-08-21 21:20:27 -04:00
parent 1a16e9f763
commit d445d633b4
7 changed files with 211 additions and 77 deletions

View File

@@ -1,3 +0,0 @@
from django.db import models
# Create your models here.

View File

@@ -1,3 +0,0 @@
from django.db import models
# Create your models here.

View File

@@ -52,6 +52,15 @@
margin-left: 2em;
}
.search-btn {
border: none;
background-color: #00000000;
}
.search-box {
height: 2em;
}
/****************************************************************************
* Grid. *
****************************************************************************/

BIN
viewer/static/imgs/find.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -8,98 +8,150 @@
</title>
<link href="{% static 'css/styles.css' %}" rel="stylesheet">
</head>
<body class="background">
{% if images|length > 0 %}
<!-- Navigation bar. -->
<table class="fc mauto">
<tr>
<!-- Home button. -->
<td>
<a href="/gallery/" class="mr-2">
<img src="{% static 'imgs/gohome.png' %}" class="small-nav-icon">
</a>
</td>
<!-- Back button. -->
{% if not search %}
<td>
<a href=".." class="mr-2">
<img src="{% static 'imgs/back.png' %}" class="small-nav-icon">
</a>
</td>
{% endif %}
<!-- Directory path. -->
<td>
<h1 class="mr-2">
{{request.path}} - Files ({{num_files}})
{% if not search %}
{{request.path}} - Files: {{num_files}}
{% else %}
Search: {{search_text}} - Files: {{num_files}}
{% endif %}
</h1>
</td>
<!-- Page links. -->
{% if num_pages > 1 %}
<td>
<div class="mauto">
{% for page in pages %}<a href="./?page={{page}}">{{page}}</a>{% if not forloop.last %}<span> </span>{% endif %}{% endfor %}
{% for page in pages %}<a href="./?page={{page}}{%if search %}&{{search}}{% endif %}">{{page}}</a>{% if not forloop.last %}<span> </span>{% endif %}{% endfor %}
</div>
</td>
{% endif %}
</tr>
</table>
<div class="centered-container">
<!-- Search form. -->
{% if not search %}
<form action="{% url 'gallery_view_root' %}" method="GET">
<table class="fc mauto">
<tr>
{% if page != 1 %}
<td class="fc">
<a href="./?page={{prev_page}}">
<img src="{% static 'imgs/back.png' %}" class="navigation-icon">
</a>
<!-- Search title. -->
<td>
<h3>
Search:
</h3>
</td>
{% endif %}
<td class="fc">
<table class="mauto">
<tbody>
{% for row in images %}
<tr>
{% for cell in row %}
<td class="column">
<a href="{{cell.path}}">
<img src="{{cell.thumbnail}}">
<br>
<span>
{{cell.path|truncatechars:15}}
</span>
</a>
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<!-- Search bar. -->
<td>
<input type="text" name="search" class="search-box">
</td>
{% if page != num_pages %}
<td class="fc">
<a href="./?page={{next_page}}">
<img src="{% static 'imgs/forward.png' %}" class="navigation-icon">
</a>
<!-- Search submit. -->
<td>
<button type="submit" class="search-btn">
<img src="{% static 'imgs/find.png' %}" class="small-nav-icon">
</button>
</td>
{% endif %}
</tr>
</table>
</div>
</form>
{% endif %}
<!-- Images in current directory. -->
{% if images|length > 0 %}
<table class="fc mauto">
<tr>
<!-- Previous page button. -->
{% if page != 1 %}
<td class="fc">
<a href="./?page={{prev_page}}{%if search %}&{{search}}{% endif %}">
<img src="{% static 'imgs/back.png' %}" class="navigation-icon">
</a>
</td>
{% endif %}
<!-- Image rows. -->
<td class="fc">
<table class="mauto">
<tbody>
{% for row in images %}
<tr>
{% for image in row %}
<td class="column">
<a href="{{image.path}}">
<!-- Thumbnail. -->
<img src="{{image.thumbnail}}">
<br>
<!-- Image name. -->
<span>
{{image.name|truncatechars:15}}
</span>
</a>
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</td>
<!-- Next page button. -->
{% if page != num_pages %}
<td class="fc">
<a href="./?page={{next_page}}{%if search %}&{{search}}{% endif %}">
<img src="{% static 'imgs/forward.png' %}" class="navigation-icon">
</a>
</td>
{% endif %}
</tr>
</table>
{% endif %}
{% if subdirs|length > 0 %}
<!-- Sub-directories title. -->
<div class="centered-container">
<h1>
Sub-directories
</h1>
</div>
<!-- Sub-directory rows. -->
<div class="centered-container">
<table class="mauto">
<tbody>
{% for row in subdirs %}
<tr>
{% for cell in row %}
{% for subdir in row %}
<td class="column">
{% if request.path == '/gallery/' %}
<a href="{{cell.name}}">
{% else %}
<a href="{{request.path}}{{cell.name}}">
{% endif %}
<a href="{{subdir.path}}">
<img src="{% static 'imgs/folder-pictures.png' %}">
<br>
<span>
{{cell.name}}
{{subdir.name}}
</span>
</a>
</td>

View File

@@ -8,14 +8,19 @@
</title>
<link href="{% static 'css/styles.css' %}" rel="stylesheet">
</head>
<body class="background">
<!-- Navigation. -->
<table class="fc mauto">
<tr>
<!-- Home button. -->
<td>
<a href="/gallery/">
<img src="{% static 'imgs/gohome.png' %}" class="small-nav-icon">
</a>
</td>
<!-- Back button. -->
<td>
<a href="..">
<img src="{% static 'imgs/back.png' %}" class="small-nav-icon">
@@ -23,8 +28,11 @@
</td>
</tr>
</table>
<!-- Image view. -->
<table class="fc mauto">
<tr>
<!-- Previous image. -->
<td>
{% if prev %}
<a href="../{{prev}}">
@@ -32,6 +40,8 @@
</a>
{% endif %}
</td>
<!-- Current image. -->
<td>
<div class="image-container">
<a href="{{image_path}}" target="_blank">
@@ -39,6 +49,8 @@
</a>
</div>
</td>
<!-- Next image. -->
<td>
{% if next %}
<a href="../{{next}}">

View File

@@ -6,10 +6,11 @@ from math import ceil
import filetype
# Django imports.
from django.http import HttpResponseNotFound
from django.conf import settings
from django.shortcuts import (render,
redirect)
from django.http import HttpResponseNotFound
from django.conf import settings
from django.utils.http import urlencode
from django.shortcuts import (render,
redirect)
# Project imports.
from .utils import make_thumbnail
@@ -26,6 +27,31 @@ IMAGES_PER_PAGE = CELLS_PER_ROW * ROWS_PER_PAGE
# View functions. #
###########################################################################################
def do_recursive_search(start_path, query):
"""
Gets all images and sub-directories inside the start_path whose name matches the given query,
and then joins the results recursively by iterating in each sub-directory.
"""
# Get all sub-dirs and images that match the query.
subdirs = sorted([i.absolute() for i in start_path.iterdir() if i.is_dir() and query.lower() in i.name.lower()])
images = sorted([i for i in start_path.iterdir() if i.is_file() and filetype.is_image(str(i)) and query.lower() in i.name.lower()])
# For all sub-directories, regardless of the query.
for subdir in sorted([i for i in start_path.iterdir() if i.is_dir()]):
# Do a recursive search.
rec_subdirs, rec_images = do_recursive_search(subdir, query.lower())
# Join the results if any.
subdirs.extend(rec_subdirs)
images.extend(rec_images)
return subdirs, images
###########################################################################################
# View functions. #
###########################################################################################
def gallery_view(request, path = None):
"""
Shows a list of subdirectories and image files inside the given path.
@@ -33,6 +59,10 @@ def gallery_view(request, path = None):
"""
def list2rows(lst, cells = CELLS_PER_ROW):
"""
Converts a list into a matrix with the given amount of cells per row.
"""
rows = []
i = 0
while i < len(lst):
@@ -46,64 +76,101 @@ def gallery_view(request, path = None):
i += cells
return rows
# Get the absolute path to show if any, else show the base gallery path.
full_path = settings.GALLERY_ROOT.joinpath(path) if path is not None else settings.GALLERY_ROOT
if full_path.exists():
if full_path.is_dir():
subdirs = sorted([i for i in full_path.iterdir() if i.is_dir()])
images = sorted([i for i in full_path.iterdir() if i.is_file() and filetype.is_image(str(i))])
img_data = []
num_pages = ceil((len(images) / CELLS_PER_ROW) / ROWS_PER_PAGE)
# Get the search query from the request, if any.
search = request.GET.get('search', default = '')
if full_path.exists():
# If the path exists then check if it points to a directory or an image.
if full_path.is_dir():
if search == '':
# If there is no search query then get all images and sub-directories of the current path.
subdirs = sorted([i for i in full_path.iterdir() if i.is_dir()])
images = sorted([i for i in full_path.iterdir() if i.is_file() and filetype.is_image(str(i))])
else:
# If there is a search query then search the current directory recursively.
subdirs, images = do_recursive_search(full_path, search)
# For every sub-directory found, prepare it's name and path for rendering.
subdir_data = []
for subdir in subdirs:
subdir_data.append({
'path': '/gallery/' + str(subdir.relative_to(settings.GALLERY_ROOT)),
'name': subdir.name
})
# Get the page number to show, if any. Default to the first one if unavailable or error.
try:
page = int(request.GET.get('page', 1))
except ValueError:
page = 1
# Compute the page offset to show.
num_pages = ceil((len(images) / CELLS_PER_ROW) / ROWS_PER_PAGE)
page_offset = IMAGES_PER_PAGE * (page - 1)
# Slice the images found with the page offset and prepare them for rendering.
img_data = []
for image in images[page_offset : page_offset + IMAGES_PER_PAGE]:
# Create thumbnails as needed.
make_thumbnail(image)
img_context = {
'path': image.name,
# Get the path of the image relative to the gallery root.
rel_path = image.relative_to(settings.GALLERY_ROOT)
# For each image, prepare it's path, thumbnail path and name for rendering.
img_data.append({
'path': '/gallery/' + str(rel_path),
'name': image.name,
'thumbnail': '/thumbs/' + path + '/' + image.name if path is not None else '/thumbs/' + image.name
}
img_data.append(img_context)
print(page)
'thumbnail': '/thumbs/' + str(rel_path)
})
# Rendering context.
context = {
'path': path,
'subdirs': list2rows(subdirs),
'images': list2rows(img_data),
'pages': range(1, num_pages + 1),
'num_files': len(images),
'page': page,
'prev_page': page - 1,
'next_page': page + 1,
'num_pages': num_pages
'path': path,
'subdirs': list2rows(subdir_data),
'images': list2rows(img_data),
'pages': range(1, num_pages + 1),
'num_files': len(images),
'page': page,
'prev_page': page - 1,
'next_page': page + 1,
'num_pages': num_pages,
'search': urlencode({'search': search}) if search != '' else None,
'search_text': search
}
# Glorious success!
return render(request, 'gallery_view.html', context)
else:
# If the path points to an image, then get it's real path, and parent directory path.
image = Path('/imgs/').joinpath(path)
img_dir = settings.GALLERY_ROOT.joinpath(path).parent
# Then get all sibling images.
images = sorted([i.name for i in img_dir.iterdir() if i.is_file() and filetype.is_image(str(i))])
# Get the current image's index in it's directory.
index = images.index(image.name)
# Get the previous and next image indices.
previous = index - 1 if index > 0 else None
following = index + 1 if index < len(images) - 1 else None
# Set the current, previous and next images as the rendering context.
context = {
'image_path': image,
'prev': images[previous] if previous is not None else None,
'next': images[following] if following is not None else None
}
# Glorious success!
return render(request, 'image_view.html', context)
else:
# 404 if the path wasn't found.
return HttpResponseNotFound('Not found')