Django 版本更新 Django: 3.1.9 从 Django: 3.1.8 后出现错误“SuspiciousFileOperation”

asc*_*row 3 python django django-models python-3.x

更新到 Django: 3.1.9 后,我收到此错误,在 Django: 3.1.8 上它工作正常。

我有一个带有 FileField 的文件模型,如下所示:

class JobFiles(BaseModel):
    category = models.CharField(max_length=50, choices=FILE_CATEGORY)
    job_file = models.FileField('JobFile', upload_to=user_directory_path)
Run Code Online (Sandbox Code Playgroud)

我指定了 upload_to 选项,以便每个类别的上传方式不同:

def user_directory_path(instance, filename):
    import uuid
    if not instance.job_file_name:
        instance.job_file_name = filename
    if instance.category == 'Job Card':
        return f'job_card/{uuid.uuid4()}'
    if instance.category == 'Photos':
        return f'job_card/photos/{uuid.uuid4()}'
    if instance.category == 'Other':
        return f'job_card/other/{uuid.uuid4()}'
    return f'job_card/other/{uuid.uuid4()}'
Run Code Online (Sandbox Code Playgroud)

生成错误的代码(仔细检查文件是否存在并且它包装在文件对象中):

from django.core.files import File

def test()
    job_files = job_card.job_card_file or JobFiles(category='JobCard')
    # Get path to a temp file that was processed (existence and other checks already done)
    doc = '/tmp/mergedfile.pdf'
    with open(doc, mode='rb') as f:
        job_files.job_file = File(f)
        job_files.save()
Run Code Online (Sandbox Code Playgroud)

我收到的错误:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/code/job_cards/views.py", line 311, in job_card_maintenance_create
    job_files.save()
  File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 753, in save
    self.save_base(using=using, force_insert=force_insert,
  File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 790, in save_base
    updated = self._save_table(
  File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 895, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 933, in _do_insert
    return manager._insert(
  File "/usr/local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 1254, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1396, in execute_sql
    for sql, params in self.as_sql():
  File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1339, in as_sql
    value_rows = [
  File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1340, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1340, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1291, in pre_save_val
    return field.pre_save(obj, add=True)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/fields/files.py", line 308, in pre_save
    file.save(file.name, file.file, save=False)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/fields/files.py", line 87, in save
    name = self.field.generate_filename(self.instance, name)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/fields/files.py", line 322, in generate_filename
    filename = validate_file_name(filename)
  File "/usr/local/lib/python3.9/site-packages/django/core/files/utils.py", line 8, in validate_file_name
    raise SuspiciousFileOperation("File name '%s' includes path elements" % name)

Exception Type: SuspiciousFileOperation at /job_cards/create/
Exception Value: File name '/tmp/a1134065293b47c1a054c8fc1481ec93.pdf' includes path elements
Run Code Online (Sandbox Code Playgroud)

我尝试过的: 降级到 3.1.8(有效) 将字符串传递到 FileField 有效,但随后它不会执行 upload_to。尝试将文件保存在“Base”文件夹和“Media”文件夹中(仍然出现相同的错误)

wiz*_*g64 5

我发现 django 的新缓解代码与项目自己的 File 和 ImageFile 默认行为不一致,即从您为构造函数提供的对象中复制确切的文件名。

对您的代码应用这样的更改应该可以修复它,就像它修复了我的一样:

     doc = '/tmp/mergedfile.pdf'
     with open(doc, mode='rb') as f:
-         job_files.job_file = File(f)
+         job_files.job_file = File(f, name=os.path.basename(doc))
          job_files.save()
Run Code Online (Sandbox Code Playgroud)

编辑:该错误现已在今天 5 月 13 日发布的 django 版本 2.23、版本 2.2.23、3.1.11、3.2.3 中修复