保存模型'产品'后,我希望上传的图像命名与pk相同,例如22.png或34.gif我不想仅仅更改名称的图像格式。如何才能做到这一点?我的模型到目前为止的例子......
image = models.ImageField(
upload_to="profiles",
height_field="image_height",
width_field="image_width",
null=True,
blank=True,
editable=True,
help_text="Profile Picture",
verbose_name="Profile Picture"
)
image_height = models.PositiveIntegerField(null=True, blank=True, editable=False, default="100")
image_width = models.PositiveIntegerField(null=True, blank=True, editable=False, default="100")
答案 0 :(得分:66)
您可以将函数传递到upload_to
字段:
def f(instance, filename):
ext = filename.split('.')[-1]
if instance.pk:
return '{}.{}'.format(instance.pk, ext)
else:
pass
# do something if pk is not there yet
我的建议是返回一个随机文件名而不是{pk}.{ext}
。作为奖励,它会更安全。
Django会调用此函数来确定文件的上传位置。这意味着您的函数负责返回文件的整个路径,包括文件名。下面是修改过的功能,您可以在其中指定上传的位置以及如何使用它:
import os
from uuid import uuid4
def path_and_rename(path):
def wrapper(instance, filename):
ext = filename.split('.')[-1]
# get filename
if instance.pk:
filename = '{}.{}'.format(instance.pk, ext)
else:
# set filename as random string
filename = '{}.{}'.format(uuid4().hex, ext)
# return the whole path to the file
return os.path.join(path, filename)
return wrapper
FileField(upload_to=path_and_rename('upload/here/'), ...)
答案 1 :(得分:19)
Django 1.7和更新版本不会像这样的功能进行迁移。基于@ miki275和this票的回答,你需要让你的功能如下:
import os
from uuid import uuid4
from django.utils.deconstruct import deconstructible
@deconstructible
class UploadToPathAndRename(object):
def __init__(self, path):
self.sub_path = path
def __call__(self, instance, filename):
ext = filename.split('.')[-1]
# get filename
if instance.pk:
filename = '{}.{}'.format(instance.pk, ext)
else:
# set filename as random string
filename = '{}.{}'.format(uuid4().hex, ext)
# return the whole path to the file
return os.path.join(self.sub_path, filename)
FileField(upload_to=UploadToPathAndRename(os.path.join(MEDIA_ROOT, 'upload', 'here'), ...)
答案 2 :(得分:6)
您可以将upload_to
指定的字符串替换为docs中所述的可调用字符串。但是,我怀疑在使用upload_to
参数时主键可能不可用。
答案 3 :(得分:0)
另一个选项,就是按照此回答https://stackoverflow.com/a/15141228/3445802,我们在需要%Y/%m/%d
的返回路径时发现了问题,例如:
FileField(upload_to=path_and_rename('upload/here/%Y/%m/%d'), ...)
所以,我们用这个处理它:
FileField(upload_to=path_and_rename('upload/here/{}'.format(time.strftime("%Y/%m/%d"))), ...)
确保已导入模块
time
。
答案 4 :(得分:0)
默认情况下,Django保留上传文件的原始名称,但是您很可能希望将其重命名为其他名称(例如对象的ID)。幸运的是,使用Django表单的ImageField或FileField,您可以将可调用函数分配给upload_to参数以进行重命名。例如:
from django.db import models
from django.utils import timezone
import os
from uuid import uuid4
def path_and_rename(instance, filename):
upload_to = 'photos'
ext = filename.split('.')[-1]
# get filename
if instance.pk:
filename = '{}.{}'.format(instance.pk, ext)
else:
# set filename as random string
filename = '{}.{}'.format(uuid4().hex, ext)
# return the whole path to the file
return os.path.join(upload_to, filename)
以及在“模型”字段中:
class CardInfo(models.Model):
...
photo = models.ImageField(upload_to=path_and_rename, max_length=255, null=True, blank=True)
在此示例中,所有上传的图像都将重命名为CardInfo对象的主键,即id_number。