Merge pull request #2641 from SchrodingersGat/report-cache-fixes

Report cache fixes
This commit is contained in:
Oliver 2022-02-18 08:54:09 +11:00 committed by GitHub
commit 0f7b6e77ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 36 deletions

View File

@ -225,13 +225,14 @@ class ReportPrintMixin:
outputs.append(report.render_as_string(request))
else:
outputs.append(report.render(request))
except TemplateDoesNotExist:
filename = report.template
except TemplateDoesNotExist as e:
template = str(e)
if not template:
template = report.template
return Response(
{
'error': _(f"Template file '{filename}' is missing or does not exist"),
'error': _(f"Template file '{template}' is missing or does not exist"),
},
status=400,
)
@ -269,13 +270,16 @@ class ReportPrintMixin:
else:
pdf = outputs[0].get_document().write_pdf()
except TemplateDoesNotExist:
except TemplateDoesNotExist as e:
filename = report.template
template = str(e)
if not template:
template = report.template
return Response(
{
'error': _(f"Template file '{filename}' is missing or does not exist"),
'error': _(f"Template file '{template}' is missing or does not exist"),
},
status=400,
)

View File

@ -14,12 +14,12 @@ import datetime
from django.urls import reverse
from django.db import models
from django.conf import settings
from django.core.cache import cache
from django.core.exceptions import ValidationError, FieldError
from django.template.loader import render_to_string
from django.template import Template, Context
from django.core.files.storage import FileSystemStorage
from django.core.validators import FileExtensionValidator
import build.models
@ -43,32 +43,12 @@ except OSError as err: # pragma: no cover
logger = logging.getLogger("inventree")
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):
return super().get_available_name(name, max_length)
def rename_template(instance, filename):
"""
Helper function for 'renaming' uploaded report files.
Pass responsibility back to the calling class,
to ensure that files are uploaded to the correct directory.
"""
return instance.rename_file(filename)
@ -155,7 +135,23 @@ class ReportBase(models.Model):
filename = os.path.basename(filename)
return os.path.join('report', 'report_template', self.getSubdir(), filename)
path = os.path.join('report', 'report_template', self.getSubdir(), filename)
fullpath = os.path.join(settings.MEDIA_ROOT, path)
fullpath = os.path.abspath(fullpath)
# If the report file is the *same* filename as the one being uploaded,
# remove the original one from the media directory
if str(filename) == str(self.template):
if os.path.exists(fullpath):
logger.info(f"Deleting existing report template: '{filename}'")
os.remove(fullpath)
# Ensure that the cache is cleared for this template!
cache.delete(fullpath)
return path
@property
def extension(self):
@ -522,16 +518,20 @@ def rename_snippet(instance, filename):
path = os.path.join('report', 'snippets', filename)
fullpath = os.path.join(settings.MEDIA_ROOT, path)
fullpath = os.path.abspath(fullpath)
# 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)
# Ensure that the cache is deleted for this snippet
cache.delete(fullpath)
return path