upload_to动态生成的网址可调用

时间:2015-06-15 10:47:39

标签: python django models

我已经看过很多关于这个问题的帖子而没有真正理解如何解决它。

我有这个型号:

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

<name>/logo/<filename>
<name>/history/<filename>
<name>/whatever/<filename>

关于我能做什么的任何想法?

1 个答案:

答案 0 :(得分:2)

看起来像(重新阅读你的帖子并不是100%明确的)你想要的是partial application。好消息,它是Python的stdlib:

的一部分
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")
        )

如果您的模型中有多个FileFieldImageField,并且不想重复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")
        )