Basic functionality ready.

This commit is contained in:
2023-07-30 18:55:12 -04:00
parent 0cc9e55db0
commit 721e4f8107
16 changed files with 301 additions and 18 deletions

View File

@@ -10,6 +10,7 @@ For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/ https://docs.djangoproject.com/en/4.2/ref/settings/
""" """
import os
from pathlib import Path from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
@@ -25,18 +26,22 @@ SECRET_KEY = 'django-insecure-#_89g9-8to*_ogxz_e0jpnqlreo0hy10odxc_)99$cs66=#7(*
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
ALLOWED_HOSTS = ['127.0.0.1', '192.168.3.42', 'nibasa', 'imgs.nibasa'] ALLOWED_HOSTS = []
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
# Django apps.
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
# Project apps.
'viewer'
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@@ -116,8 +121,19 @@ USE_TZ = True
# https://docs.djangoproject.com/en/4.2/howto/static-files/ # https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/' STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Gallery paths.
GALLERY_ROOT = None
THUMBNAILS_ROOT = None
# Attempt to load local settings if any.
try:
from .local_settings import *
except ImportError:
pass

View File

@@ -14,9 +14,26 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin
from django.urls import path # Django imports.
from django.conf import settings
from django.conf.urls.static import static
from django.urls import (path,
include)
# Project imports
from home.views import index
###########################################################################################
# URL Patterns. #
###########################################################################################
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), # Index.
] path('', index, name = 'home'),
# Add invoices app urls.
path('gallery/', include('viewer.urls')),
] + static(settings.STATIC_URL, document_root = settings.STATIC_ROOT)\
+ static('imgs/', document_root = settings.GALLERY_ROOT)\
+ static('thumbs/', document_root = settings.THUMBNAILS_ROOT)

0
home/__init__.py Normal file
View File

6
home/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class HomeConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'home'

View File

3
home/models.py Normal file
View File

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

5
home/views.py Normal file
View File

@@ -0,0 +1,5 @@
from django.shortcuts import redirect
# Create your views here.
def index(request):
return redirect('gallery_view_root')

View File

@@ -1,7 +1,4 @@
Django==4.2.3 Django==4.2.3
django-minify-html==1.6.0
django-pipeline==2.1.0
django-img==0.1.5
unidecode==1.3.6
Pillow==10.0.0
gunicorn==21.2.0 gunicorn==21.2.0
filetype==1.2.0
Pillow==10.0.0

View File

@@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@@ -0,0 +1,50 @@
# Standard library imports.
from pathlib import Path
# External library imports.
import filetype
from PIL import Image
# Django imports.
from django.core.management.base import BaseCommand
from django.conf import settings
# Project imports.
from viewer.utils import make_thumbnail
###########################################################################################
# Constants. #
###########################################################################################
THUMB_SIZE = (128, 128)
###########################################################################################
# Command subclass. #
###########################################################################################
class Command(BaseCommand):
"""
Assorted data fix and clean up commands for the Meters module.
"""
def _make_missing_thumbnails(self, directory):
"""
Goes through the GALLERY_ROOT directory recursively and creates a new thumbnail
for each image that does not have a corresponding file (same name) in the THUMBNAILS_ROOT
directory.
"""
# Make a thumbnail for each file in the current directory.
for image in [i for i in directory.iterdir() if i.is_file() and filetype.is_image(str(i))]:
make_thumbnail(image)
# Handle each sub-directory recursively.
for subdir in [i for i in directory.iterdir() if i.is_dir()]:
self._make_missing_thumbnails(subdir)
def handle(self, *args, **options):
try:
self._make_missing_thumbnails(settings.GALLERY_ROOT)
except KeyboardInterrupt as e:
self.stderr.write(self.style.ERROR('\nInterrupted'))

View File

@@ -0,0 +1,66 @@
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, height=device-height" />
<title>
Folder: {{request.path}}
</title>
<link href="{% static 'css/styles.css' %}" rel="stylesheet">
</head>
<body class="background">
<div class="centered-container">
<a href="/gallery/">
<img src="{% static 'imgs/gohome.png' %}">
</a>
<a href="..">
<img src="{% static 'imgs/back.png' %}">
</a>
</div>
{% if images|length > 0 %}
<div class="centered-container">
<h1>
Files
</h1>
</div>
<div class=grid-container>
<div class="grid">
{% for image in images %}
<div class="column">
<a href="{{image.path}}">
<img src="{{image.thumbnail}}">
</a>
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% if subdirs|length > 0 %}
<div class="centered-container">
<h1>
Sub-directories
</h1>
</div>
<div class=grid-container>
<div class="grid">
{% for dir in subdirs%}
<div class="column">
{% if request.path == '/gallery/' %}
<a href="{{dir.name}}">
{% else %}
<a href="{{request.path}}{{dir.name}}">
{% endif %}
<div class="grid-icon">
<img src="{% static 'imgs/folder-pictures.png' %}">
</div>
<span>
{{dir.name}}
</span>
</a>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</body>
</html>

View File

@@ -0,0 +1,28 @@
{% load static %}
<!DOCTYPE html>
<html style="height:100%;">
<head>
<meta name="viewport" content="width=device-width, height=device-height" />
<title>
Vieweing folder: {{path}}
</title>
<link href="{% static 'css/styles.css' %}" rel="stylesheet">
</head>
<body class="background">
<div class="centered-container">
<a href="/gallery/">
<img src="{% static 'imgs/gohome.png' %}">
</a>
<a href="..">
<img src="{% static 'imgs/back.png' %}">
</a>
</div>
<div class="centered-container">
<div class="image-container">
<a href="{{image_path}}" target="_blank">
<img src="{{image_path}}" class="image">
</a>
</div>
</div>
</body>
</html>

View File

@@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

18
viewer/urls.py Normal file
View File

@@ -0,0 +1,18 @@
# Django imports
from django.urls import path
from django.contrib.auth.decorators import login_required
# Module imports
from .views import (
gallery_view
)
###########################################################################################
# URL Patterns. #
###########################################################################################
urlpatterns = [
# Views.
path('', gallery_view, name = 'gallery_view_root'),
path('<path:path>/', gallery_view, name = 'gallery_view_path'),
]

29
viewer/utils.py Normal file
View File

@@ -0,0 +1,29 @@
# Standard library imports.
from pathlib import Path
# External library imports.
from PIL import Image
# Django imports.
from django.conf import settings
###########################################################################################
# Helper functions. #
###########################################################################################
def make_thumbnail(image):
"""
Creates a thumbnail in the corresponding THUMBNAILS_ROOT directory for the given image.
:param image: A pathlib.Path instance pointing to a file inside the GALLERY_ROOT directory.
"""
if image.exists():
thumb_path = Path(str(image).replace(str(settings.GALLERY_ROOT), str(settings.THUMBNAILS_ROOT)))
thumb_path.parent.mkdir(parents = True, exist_ok = True)
if not thumb_path.exists():
with Image.open(str(image)) as pilimg:
pilimg.thumbnail(THUMB_SIZE)
pilimg.save(str(thumb_path))

View File

@@ -1,3 +1,57 @@
from django.shortcuts import render # Standard library imports.
from pathlib import Path
# Create your views here. # External library imports.
import filetype
# Django imports.
from django.http import HttpResponseNotFound
from django.conf import settings
from django.shortcuts import (render,
redirect)
# Project imports.
from .utils import make_thumbnail
###########################################################################################
# View functions. #
###########################################################################################
def gallery_view(request, path = None):
"""
Shows a list of subdirectories and image files inside the given path.
The path should be inside the GALLERY_ROOT path, otherwise a 404 error will be thrown.
"""
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))])
display_images = []
for image in images:
make_thumbnail(image)
img_context = {
'path': image.name,
'name': image.name,
'thumbnail': '/thumbs/' + path + '/' + image.name if path is not None else '/thumbs/' + image.name
}
display_images.append(img_context)
context = {
'path': path,
'subdirs': subdirs,
'images': display_images
}
return render(request, 'gallery_view.html', context)
else:
return render(request, 'image_view.html', {'image_path': Path('/imgs/').joinpath(path)})
else:
return HttpResponseNotFound('Not found')