我有一个更可定制的Aidan Ewen解决方案实现。
有什么新东西?
- 你可以将要在文件名中使用的字段作为列表发送(按预定顺序)
- ^ 其中之一必须是唯一的
- ^ 否则,此列表必须包括唯一字段元组之一
- ^ 否则,你发送的字段将被忽略,并将使用uuid4作为文件名
示例1:
image = models.ImageField(upload_to=PathAndRename('images/').wrapper)
filename = {pk}.{ext}
例子2:
name = models.CharField(max_length=20)
image = models.ImageField(upload_to=PathAndRename('images/', ['name']).wrapper)
filename = {uuid4}.{ext}
例子 3:
name = models.CharField(max_length=20, unique=True)
no = models.CharField(max_length=10)
image = models.ImageField(upload_to=PathAndRename('images/', ['name','no']).wrapper)
filename = {name}_{no}.{ext}
例子 4:
name = models.CharField(max_length=20)
no = models.CharField(max_length=10)
image = models.ImageField(upload_to=PathAndRename('images/', ['name','no']).wrapper)
class Meta:
unique_together = ('name', 'no')
filename = {name}_{no}.{ext}
我可能忘记了给出更多的例子,但你可以从下面的代码中理解:
class PathAndRename:
"""
fields to use for naming, order is important
"""
def __init__(self, path, fields_to_use=('pk',)):
self.path = path
self.fields_to_use = fields_to_use
def wrapper(self, instance, filename):
ext = '.'.join(filename.split('.')[1:])
if self.is_any_unique_exist(instance):
filename = '{}.{}'.format(self.get_filename_by_fields(instance), ext)
elif self.is_any_unique_together_exist(instance):
filename = '{}.{}'.format(self.get_filename_by_fields(instance), ext)
else:
filename = '{}.{}'.format(uuid4().hex, ext)
return os.path.join(self.path, filename)
def is_any_unique_exist(self, instance):
if 'pk' in self.fields_to_use:
return True
return any([instance._meta.get_field(field).unique for field in self.fields_to_use if hasattr(instance, field)])
def is_any_unique_together_exist(self, instance):
if hasattr(instance._meta, 'unique_together'):
if isinstance(instance._meta.unique_together, (list, tuple)):
for uniques in instance._meta.unique_together:
if all(map(lambda field: field in self.fields_to_use, uniques)):
return True
else:
if all(map(lambda field: field in self.fields_to_use, instance._meta.unique_together)):
return True
return False
def get_filename_by_fields(self, instance):
return '_'.join([str(getattr(instance, field)) for field in self.fields_to_use])
警告:对于此 upload_to 问题的每种基于方法的解决方案,当您放弃使用这些解决方案时,都会对已执行的迁移文件造成问题。如果您使用这些解决方案一段时间后将其删除,则旧的迁移将因为这些方法不存在而失败。(当然,您可以通过修改旧的迁移文件来解决此问题)
upload_to=path_and_rename, ...
- miki725