upload_to 动态生成 url 可调用
upload_to dynamically generated url to callable
我看过很多关于这个问题的post,但并没有真正理解如何解决它。
我有这个型号:
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField()
我想按照此模板将图像保存到媒体根目录:
<name>/logo/<filename>
乍一看,我想做的是:
logo = models.ImageField(upload_to="{}/logo/".format(name))
但它引发了这个错误:AttributeError: 'TextField' object has no attribute 'model'
使用 callable 会很好,部分虽然:
def upload_to_project(self, filename):
url = ("%s/%s") % (self.name, filename)
return url
并使用:
logo = models.ImageField(upload_to=upload_to_project)
至少我有:<name>/<filename>
但是在这种情况下如何传递参数呢?我想重用我的功能在其他子文件夹中上传,而不仅仅是 logo
as:
<name>/logo/<filename>
<name>/history/<filename>
<name>/whatever/<filename>
知道我能做什么吗?
看起来 (重新阅读您的 post 它不是 100% 清楚) 您想要的是 partial application。好消息,它是 Python 标准库的一部分:
import os
from functools import partial
def generic_upload_to(instance, filename, folder):
return os.path.join(instance.name, folder, filename)
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField(
upload_to=partial(generic_upload_to, folder="logo")
)
请注意,此实现假定 instance
具有 name
属性...如果您要用作第一部分的实例属性也必须是可配置的,您可以重写 upload_to
作为:
def generic_upload_to(instance, filename, folder, attrname):
return os.path.join(getattr(instance, attrname), folder, filename)
然后用作
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField(
upload_to=partial(generic_upload_to, attrname="name", folder="logo")
)
如果您的模型中有多个 FileField
或 ImageField
,并且不想重复 attrname
部分:
class Something(TimeStampedModel):
my_upload_to = partial(generic_upload_to, attrname="label")
label = models.CharField(max_length=100, default='no label')
logo = models.ImageField(
upload_to=partial(my_upload_to, folder="logo")
)
attachment = models.FileField(
upload_to=partial(my_upload_to, folder="attachment")
)
我看过很多关于这个问题的post,但并没有真正理解如何解决它。
我有这个型号:
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField()
我想按照此模板将图像保存到媒体根目录:
<name>/logo/<filename>
乍一看,我想做的是:
logo = models.ImageField(upload_to="{}/logo/".format(name))
但它引发了这个错误:AttributeError: 'TextField' object has no attribute 'model'
使用 callable 会很好,部分虽然:
def upload_to_project(self, filename):
url = ("%s/%s") % (self.name, filename)
return url
并使用:
logo = models.ImageField(upload_to=upload_to_project)
至少我有:<name>/<filename>
但是在这种情况下如何传递参数呢?我想重用我的功能在其他子文件夹中上传,而不仅仅是 logo
as:
<name>/logo/<filename>
<name>/history/<filename>
<name>/whatever/<filename>
知道我能做什么吗?
看起来 (重新阅读您的 post 它不是 100% 清楚) 您想要的是 partial application。好消息,它是 Python 标准库的一部分:
import os
from functools import partial
def generic_upload_to(instance, filename, folder):
return os.path.join(instance.name, folder, filename)
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField(
upload_to=partial(generic_upload_to, folder="logo")
)
请注意,此实现假定 instance
具有 name
属性...如果您要用作第一部分的实例属性也必须是可配置的,您可以重写 upload_to
作为:
def generic_upload_to(instance, filename, folder, attrname):
return os.path.join(getattr(instance, attrname), folder, filename)
然后用作
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField(
upload_to=partial(generic_upload_to, attrname="name", folder="logo")
)
如果您的模型中有多个 FileField
或 ImageField
,并且不想重复 attrname
部分:
class Something(TimeStampedModel):
my_upload_to = partial(generic_upload_to, attrname="label")
label = models.CharField(max_length=100, default='no label')
logo = models.ImageField(
upload_to=partial(my_upload_to, folder="logo")
)
attachment = models.FileField(
upload_to=partial(my_upload_to, folder="attachment")
)