如何在Django中强制上传文件名唯一?

70 投票
7 回答
44926 浏览
提问于 2025-04-15 21:49

在使用Django上传照片时,怎么才能给每张照片起一个独一无二的名字呢?我想确保每个名字只用一次。有没有什么Pinax应用可以做到这一点,可能是用GUID(全局唯一标识符)来实现?

7 个回答

12

在写这个回答的时候,似乎你不需要做什么特别的事情就能实现这个功能。如果你设置一个 FileField,并给它一个固定的 upload_to 属性,Django 的存储系统会自动处理文件命名的问题。也就是说,如果有人上传了一个重复的文件名,Django 会随机生成一个新的独特文件名来避免冲突。

这个功能在 Django 1.10 版本上有效。

20

一个更好的方法是使用你在helpers.py里定义的一个公共类。这样,你就可以在不同的应用中重复使用这个随机文件生成器。

在你的helpers.py文件中:

import os
import uuid
from django.utils.deconstruct import deconstructible


@deconstructible
class RandomFileName(object):
    def __init__(self, path):
        self.path = os.path.join(path, "%s%s")

    def __call__(self, _, filename):
        # @note It's up to the validators to check if it's the correct file type in name or if one even exist.
        extension = os.path.splitext(filename)[1]
        return self.path % (uuid.uuid4(), extension)

然后在你的模型中,只需导入这个助手类:

from mymodule.helpers import RandomFileName 

接着就可以使用它了:

logo = models.ImageField(upload_to=RandomFileName('logos'))

参考链接:https://coderwall.com/p/hfgoiw/give-imagefield-uploads-a-unique-name-to-avoid-file-overwrites

168

使用uuid。要将其与您的模型结合起来,可以查看Django文档中关于FileField的upload_to部分。

例如,在您的models.py文件中定义以下函数:

import uuid
import os

def get_file_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (uuid.uuid4(), ext)
    return os.path.join('uploads/logos', filename)

然后,在定义您的FileField/ImageField时,将get_file_path指定为upload_to的值。

file = models.FileField(upload_to=get_file_path,
                        null=True,
                        blank=True,
                        verbose_name=_(u'Contact list'))

撰写回答