如何在Django中更改上传文件的文件名?

45 投票
9 回答
51609 浏览
提问于 2025-04-15 21:52

在Django中,上传的文件名可以更改吗?我搜索过,但没有找到答案。

我的需求是,每当上传一个文件时,它的文件名应该按照以下格式进行更改。

format = userid + transaction_uuid + file_extension

非常感谢...

9 个回答

11

如果你想让你的函数可以重复使用:

import hashlib
import datetime
import os
from functools import partial

def _update_filename(instance, filename, path):
    path = path

    filename = "..."

    return os.path.join(path, filename)

def upload_to(path):
    return partial(_update_filename, path=path)

你只需要这样使用它:

document = models.FileField(upload_to=upload_to("my/path"))
13

你需要有一个 FileField,并且要设置 upload_to,这个设置会调用一个回调函数,具体可以参考[1]

你的回调函数应该调用一个包装方法,这个方法需要接收两个参数,一个是实例,另一个是文件名。[2]

你可以根据自己的需要修改这个方法,并返回新的路径。[3]

1. 逻辑

FileField(..., upload_to=method_call(params),....)

2. 定义方法

def method_call(params):
    return u'abc'

3. 包装方法:

def wrapper(instance, filename):
    return method

这是你需要的包装方法,用来获取实例。

def wrapper(instance, filename):
... Your logic
...
return wrapper

完整代码

def path_and_rename(path, prefix):
    def wrapper(instance, filename):
        ext = filename.split('.')[-1]
        project = "pid_%s" % (instance.project.id,)
        # get filename
        if instance.pk:
            complaint_id = "cid_%s" % (instance.pk,)
            filename = '{}.{}.{}.{}'.format(prefix, project, complaint_id, ext)
        else:
            # set filename as random string
            random_id = "rid_%s" % (uuid4().hex,)
            filename = '{}.{}.{}.{}'.format(prefix, project, random_id, ext)
            # return the whole path to the file
        return os.path.join(path, filename)

    return wrapper

调用方法

sales_attach = models.FileField("Attachment", upload_to=path_and_rename("complaint_files", 'sales'), max_length=500,
                                help_text="Browse a file")

希望这对你有帮助。谢谢。

64

你是怎么上传文件的?

我猜是用的 FileField

关于 FileField.upload_to 的文档里说,

upload_to 字段可以是一个可调用的对象,比如一个函数,这个函数会被调用来获取上传路径,包括文件名。这个函数需要能接受两个参数,并返回一个 Unix 风格的路径(用正斜杠分隔),这个路径会被传递给存储系统。将会传递的两个参数是:

“instance”:这是定义了 FileField 的模型的一个实例。更具体地说,就是当前文件被附加到的那个具体实例。

“filename”:这是文件最初的名称。这个名称在确定最终的存储路径时可能会被考虑,也可能不会。

所以看起来你只需要写一个函数来处理文件名,然后返回路径就可以了。

def update_filename(instance, filename):
    path = "upload/path/"
    format = instance.userid + instance.transaction_uuid + instance.file_extension
    return os.path.join(path, format)

撰写回答