Hello all,
I have a problem with relative paths while storing files.
Snipped from settings.py
if DEBUG:
MEDIA_ROOT = BASE_DIR / "../data/"
I like to keep all uploaded files outside my source directory, even in DEBUG mode.
Snipped models.py
def directory_path(instance, filename):
directory = os.path.join(MEDIA_ROOT, f"/files/somenumber")
return os.path.join(directory, filename)
class myFile(models.Model):
file = models.FileField(upload_to=directory_path, null=True, max_length=300,
help_text=_("Select file."))
result
SuspiciousFileOperation at /test/file/new
Detected path traversal attempt in '../data/files/somenumber/filename'
The trace end:
File "lib/python3.14/site-packages/django/db/models/fields/files.py", line 360, in generate_filename
filename = validate_file_name(filename, allow_relative_path=True)
File "lib/python3.14/site-packages/django/core/files/utils.py", line 17, in validate_file_name
raise SuspiciousFileOperation(
Snipped for utils.py:
def validate_file_name(name, allow_relative_path=False):
# Remove potentially dangerous names
if os.path.basename(name) in {"", ".", ".."}:
raise SuspiciousFileOperation("Could not derive file name from '%s'" % name)
if allow_relative_path:
# Ensure that name can be treated as a pure posix path, i.e. Unix
# style (with forward slashes).
path = pathlib.PurePosixPath(str(name).replace("\\", "/"))
if path.is_absolute() or ".." in path.parts:
raise SuspiciousFileOperation(
"Detected path traversal attempt in '%s'" % name
)
elif name != os.path.basename(name):
raise SuspiciousFileOperation("File name '%s' includes path elements" % name)
return name
Now what I don’t get is, as far as I know, relative paths always have some kind of ‘..’ in them or they would be absolute paths.
But reading the code it says “yes we allow relative paths” but you can’t have any “..” in any part of the path.
How can I store files outside my source directory? What am I missing?
Django: 6.1
Pyhton: 3.14
7.1.9-1-MANJARO x86_64 GNU/Linux