Keep asset and snippet filenames the same (if possible)

This commit is contained in:
Oliver Walters 2021-02-05 13:51:25 +11:00
parent d686fb5057
commit b5e993872f

View File

@ -7,12 +7,14 @@ from __future__ import unicode_literals
import os import os
import sys import sys
import logging
import datetime import datetime
from django.db import models from django.db import models
from django.conf import settings from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.core.validators import FileExtensionValidator from django.core.validators import FileExtensionValidator
import stock.models import stock.models
@ -29,6 +31,35 @@ except OSError as err:
sys.exit(1) sys.exit(1)
logger = logging.getLogger(__name__)
class ReportFileUpload(FileSystemStorage):
"""
Custom implementation of FileSystemStorage class.
When uploading a report (or a snippet / asset / etc),
it is often important to ensure the filename is not arbitrarily *changed*,
if the name of the uploaded file is identical to the currently stored file.
For example, a snippet or asset file is referenced in a template by filename,
and we do not want that filename to change when we upload a new *version*
of the snippet or asset file.
This uploader class performs the following pseudo-code function:
- If the model is *new*, proceed as normal
- If the model is being updated:
a) If the new filename is *different* from the existing filename, proceed as normal
b) If the new filename is *identical* to the existing filename, we want to overwrite the existing file
"""
def get_available_name(self, name, max_length=None):
print("Name:", name)
return super().get_available_name(name, max_length)
def rename_template(instance, filename): def rename_template(instance, filename):
return instance.rename_file(filename) return instance.rename_file(filename)
@ -235,7 +266,19 @@ def rename_snippet(instance, filename):
filename = os.path.basename(filename) filename = os.path.basename(filename)
return os.path.join('report', 'snippets', filename) path = os.path.join('report', 'snippets', filename)
# If the snippet file is the *same* filename as the one being uploaded,
# delete the original one from the media directory
if str(filename) == str(instance.snippet):
fullpath = os.path.join(settings.MEDIA_ROOT, path)
fullpath = os.path.abspath(fullpath)
if os.path.exists(fullpath):
logger.info(f"Deleting existing snippet file: '{filename}'")
os.remove(fullpath)
return path
class ReportSnippet(models.Model): class ReportSnippet(models.Model):
@ -259,7 +302,19 @@ def rename_asset(instance, filename):
filename = os.path.basename(filename) filename = os.path.basename(filename)
return os.path.join('report', 'assets', filename) path = os.path.join('report', 'assets', filename)
# If the asset file is the *same* filename as the one being uploaded,
# delete the original one from the media directory
if str(filename) == str(instance.asset):
fullpath = os.path.join(settings.MEDIA_ROOT, path)
fullpath = os.path.abspath(fullpath)
if os.path.exists(fullpath):
logger.info(f"Deleting existing asset file: '{filename}'")
os.remove(fullpath)
return path
class ReportAsset(models.Model): class ReportAsset(models.Model):