mirror of
https://github.com/inventree/InvenTree.git
synced 2026-11-14 12:32:44 +00:00
cache base media URL
This commit is contained in:
1 parent
d14269d465
commit
e1cc803b0b
1 file changed
+64
-1
@@ -182,7 +182,70 @@ def getMediaUrl(
|
||||
if name is not None:
|
||||
file = regenerate_imagefile(file, name)
|
||||
|
||||
return default_storage.url(file.name)
|
||||
return get_media_url(file.name)
|
||||
|
||||
|
||||
# Request cache key for the default storage base URL (see get_media_url)
|
||||
MEDIA_BASE_URL_CACHE_KEY = 'media_storage_base_url'
|
||||
|
||||
# Matches '.' or '..' path segments, which urljoin() would resolve
|
||||
_DOT_SEGMENT_REGEX = re.compile(r'(^|/)\.\.?(/|$)')
|
||||
|
||||
|
||||
def _get_filesystem_base_url() -> str:
|
||||
"""Return the base URL of the default storage, if it is a plain FileSystemStorage.
|
||||
|
||||
Returns an empty string for any other storage backend
|
||||
(e.g. S3, or a subclass which may override url()),
|
||||
or if the base URL is not in the expected format.
|
||||
|
||||
The result is cached for the duration of the current request.
|
||||
"""
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
|
||||
from InvenTree.cache import get_session_cache, set_session_cache
|
||||
|
||||
base_url = get_session_cache(MEDIA_BASE_URL_CACHE_KEY)
|
||||
|
||||
if base_url is None:
|
||||
base_url = ''
|
||||
|
||||
# Note: default_storage is a LazyObject - __class__ is proxied to the wrapped storage
|
||||
if default_storage.__class__ is FileSystemStorage:
|
||||
storage_base_url = default_storage.base_url
|
||||
|
||||
if isinstance(storage_base_url, str) and storage_base_url.endswith('/'):
|
||||
base_url = storage_base_url
|
||||
|
||||
set_session_cache(MEDIA_BASE_URL_CACHE_KEY, base_url)
|
||||
|
||||
return base_url
|
||||
|
||||
|
||||
def get_media_url(name: str) -> str:
|
||||
"""Return the URL for the named file in the default (media) storage.
|
||||
|
||||
Equivalent to default_storage.url(name), but for the default FileSystemStorage
|
||||
backend the URL is constructed directly, which avoids the overhead of urljoin().
|
||||
This is significant when rendering URLs for large API list queries.
|
||||
|
||||
Arguments:
|
||||
name: The name (path) of the file within the storage
|
||||
"""
|
||||
if base_url := _get_filesystem_base_url():
|
||||
from django.utils.encoding import filepath_to_uri
|
||||
|
||||
url = filepath_to_uri(name)
|
||||
|
||||
if url is not None:
|
||||
url = url.lstrip('/')
|
||||
|
||||
# urljoin() resolves '.' and '..' segments, and collapses empty segments ('//')
|
||||
# Defer to the storage backend for these (rare) cases
|
||||
if '//' not in url and not _DOT_SEGMENT_REGEX.search(url):
|
||||
return base_url + url
|
||||
|
||||
return default_storage.url(name)
|
||||
|
||||
|
||||
def regenerate_imagefile(_file, _name: str):
|
||||
|
||||
Reference in new issue
Block a user