使用 django 在服务器上使用唯一文件名重命名照片的最佳方法是什么?我想确保每个名称只使用一次。是否有任何 pinax 应用程序可以做到这一点,也许使用 GUID?
7 回答
使用 uuid。要将其绑定到您的模型中,请参阅FileField upload_to 的Django 文档。
例如,在您的 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'))
更好的方法是在你的 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
在 Django 1.6.6、1.5.9 和 1.4.14 之前,该get_avaialable_name
函数会通过添加下划线来自动给文件一个唯一的名称。因此,例如,如果您将一个文件“test.jpg”然后将另一个文件“test.jpg”保存到您的服务器,第一个文件将被称为 test.jpg,第二个文件将被称为 test_1.jpg。
唉,这原来是对机器进行 DDOS 攻击的向量,通过向其发送数千个零字节文件进行存储,每个文件检查数千个以前的文件以查看其名称应该是什么。
正如您将在文档中看到的那样,新系统在下划线后附加了七个随机数字来解决此问题。
在撰写此答案时,您似乎不再需要做任何特别的事情来实现这一点。如果你设置了FileField
一个静态upload_to
属性,Django 存储系统会自动管理命名,这样如果上传了重复的文件名,Django 会为重复的文件随机生成一个新的唯一文件名。
适用于 Django 1.10。
您可以自己编写FileField
和改写generate_filename
。
例如:
class UniqueNameFileField(FileField):
def generate_filename(self, instance, filename):
_, ext = os.path.splitext(filename)
name = f'{uuid.uuid4().hex}{ext}'
return super().generate_filename(instance, name)
django 自动强制执行唯一的文件名。如果文件已经存在,则在文件名中附加七个唯一字符
在 django 2.2 上测试