mirror of
https://github.com/Xevion/simple-viewer.git
synced 2025-12-17 08:13:22 -06:00
begin adding more meta attributes to ServedDirectory and File models, small improves to documentation and accompanying metadata logic
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
import jsonfield
|
import jsonfield
|
||||||
from django.db import models
|
from django.db import models
|
||||||
@@ -25,33 +26,38 @@ class ServedDirectory(models.Model):
|
|||||||
|
|
||||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
|
||||||
path = models.CharField('Directory Path', max_length=260)
|
path = models.CharField('Directory Path', max_length=260)
|
||||||
|
|
||||||
recursive = models.BooleanField('Files Are Matched Recursively', default=False)
|
recursive = models.BooleanField('Files Are Matched Recursively', default=False)
|
||||||
regex_pattern = models.CharField('RegEx Matching Pattern', max_length=100, default='')
|
regex_pattern = models.CharField('RegEx Matching Pattern', max_length=100, default='')
|
||||||
regex = models.BooleanField('Directory RegEx Option', default=False)
|
regex = models.BooleanField('Directory RegEx Option', default=False)
|
||||||
match_filename = models.BooleanField('RegEx Matches Against Filename', default=True)
|
match_filename = models.BooleanField('RegEx Matches Against Filename', default=True)
|
||||||
known_subdirectories = jsonfield.JSONField('Tracked Subdirectories JSON', default=[])
|
known_subdirectories = jsonfield.JSONField('Tracked Subdirectories JSON', default=[])
|
||||||
|
|
||||||
|
lastModified = models.DateTimeField(auto_now=True)
|
||||||
|
lastRefreshed = models.DateTimeField()
|
||||||
|
initialCreation = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
"""Refresh the directory listing to see if any new files have appeared and add them to the list."""
|
"""Refresh the directory listing to see if any new files have appeared and add them to the list."""
|
||||||
# TODO: Implement separate recursive file matching implementation
|
# TODO: Implement separate recursive file matching implementation
|
||||||
# TODO: Implement RegEx filtering step
|
# TODO: Implement RegEx filtering step
|
||||||
directories = []
|
directories = []
|
||||||
files = os.listdir(self.path)
|
filenames = os.listdir(self.path)
|
||||||
for i, file in enumerate(files):
|
|
||||||
print(f'{i} / {len(files)}')
|
for i, filename in enumerate(filenames):
|
||||||
file_path = os.path.join(self.path, file)
|
file_path = os.path.join(self.path, filename)
|
||||||
|
|
||||||
if os.path.isfile(file_path):
|
if os.path.isfile(file_path):
|
||||||
# Check if the file has been entered before
|
# Check if the file has been entered before
|
||||||
entry: File
|
file: File
|
||||||
entry = self.files.filter(filename__exact=file).first()
|
file = self.files.filter(filename__exact=filename).first()
|
||||||
if entry is None:
|
|
||||||
|
if file is None:
|
||||||
# create the file entry
|
# create the file entry
|
||||||
entry = File.create(full_path=file_path, parent=self)
|
file = File.create(full_path=file_path, parent=self)
|
||||||
entry.save()
|
file.save()
|
||||||
else:
|
else:
|
||||||
if entry.thumbnail is None:
|
file.refresh()
|
||||||
entry.generate_thumbnail()
|
|
||||||
else:
|
else:
|
||||||
# directory found, remember it
|
# directory found, remember it
|
||||||
directories.append(file_path)
|
directories.append(file_path)
|
||||||
@@ -63,13 +69,35 @@ class ServedDirectory(models.Model):
|
|||||||
return self.path
|
return self.path
|
||||||
|
|
||||||
|
|
||||||
|
class ImageDimensions(models.Model):
|
||||||
|
"""
|
||||||
|
A simple model for storing the dimensions of a specific image. A tuple, in essence.
|
||||||
|
"""
|
||||||
|
|
||||||
|
x = models.PositiveIntegerField()
|
||||||
|
y = models.PositiveIntegerField()
|
||||||
|
|
||||||
|
|
||||||
class File(models.Model):
|
class File(models.Model):
|
||||||
|
"""
|
||||||
|
A File object of course represents a singular File inside the directory.
|
||||||
|
This table stores all the required metadata and paths to ensure
|
||||||
|
"""
|
||||||
|
|
||||||
path = models.CharField('Full Filepath', max_length=300)
|
path = models.CharField('Full Filepath', max_length=300)
|
||||||
filename = models.CharField('Filename', max_length=160)
|
filename = models.CharField('Filename', max_length=160)
|
||||||
mediatype = models.CharField('Mediatype', max_length=30)
|
mediatype = models.CharField('Mediatype', max_length=30)
|
||||||
directory = models.ForeignKey(ServedDirectory, on_delete=models.CASCADE, related_name='files')
|
directory = models.ForeignKey(ServedDirectory, on_delete=models.CASCADE, related_name='files')
|
||||||
thumbnail = models.CharField('Thumbnail Filename', max_length=160, null=True, default=None)
|
thumbnail = models.CharField('Thumbnail Filename', max_length=160, null=True, default=None)
|
||||||
|
|
||||||
|
lastModified = models.DateTimeField(auto_now=True)
|
||||||
|
initialCreation = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
fileLastModified = models.DateTimeField()
|
||||||
|
lastRefreshed = models.DateTimeField()
|
||||||
|
size = models.OneToOneField(ImageDimensions, on_delete=models.CASCADE)
|
||||||
|
thumbnailSize = models.OneToOneField(ImageDimensions, on_delete=models.CASCADE)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, full_path: str, parent: ServedDirectory) -> 'File':
|
def create(cls, full_path: str, parent: ServedDirectory) -> 'File':
|
||||||
"""Simple shortcut for creating a File database entry with just the path."""
|
"""Simple shortcut for creating a File database entry with just the path."""
|
||||||
@@ -80,6 +108,17 @@ class File(models.Model):
|
|||||||
directory=parent
|
directory=parent
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def refresh(self) -> None:
|
||||||
|
"""Refresh this file's metadata"""
|
||||||
|
|
||||||
|
if not self.thumbnail:
|
||||||
|
self.generate_thumbnail()
|
||||||
|
|
||||||
|
# Check the fileLastModified
|
||||||
|
fileLastModified = datetime.fromtimestamp(os.path.getmtime(self.path))
|
||||||
|
if fileLastModified != self.fileLastModified:
|
||||||
|
self.generate_thumbnail()
|
||||||
|
|
||||||
def get_url(self, directory: ServedDirectory) -> str:
|
def get_url(self, directory: ServedDirectory) -> str:
|
||||||
"""Retrieve the direct URL for a given file."""
|
"""Retrieve the direct URL for a given file."""
|
||||||
return reverse('file', args=(directory.id, self.filename))
|
return reverse('file', args=(directory.id, self.filename))
|
||||||
@@ -94,16 +133,16 @@ class File(models.Model):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def thumbnail_url(self):
|
def thumbnail_static_path(self):
|
||||||
if self.thumbnail:
|
"""Used for accessing the thumbnail via the static URL"""
|
||||||
return f'/thumbnails/{self.thumbnail}'
|
return f'/thumbnails/{self.thumbnail}'
|
||||||
return ''
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def thumbs_dir(self):
|
def thumbs_dir(self):
|
||||||
|
"""A string path to the directory containing thumbnails."""
|
||||||
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'thumbnails')
|
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'thumbnails')
|
||||||
|
|
||||||
def generate_thumbnail(self) -> None:
|
def generate_thumbnail(self, regenerate=False) -> None:
|
||||||
# TODO: Add django-background-task scheduling
|
# TODO: Add django-background-task scheduling
|
||||||
|
|
||||||
self.delete_thumbnail()
|
self.delete_thumbnail()
|
||||||
|
|||||||
Reference in New Issue
Block a user