将回调作为upload_to传递给FileField

mar*_*oxe 4 directory django filefield

我有一个抽象的模型类UploadItem来处理上传的文件.我希望每个子类能够定义upload_to路径.为此,我将回调传递给FileField的构造函数.

这是一个例子:

class UploadItem(models.Model):
    file = models.FileField(upload_to=UploadItem.get_directory) 


    class Meta:
        abstract = True
# I want videos to be storred in 'videos/' directory
class Video(UploadItem):
    def get_directory(self, instance, filename):
        return 'videos/'
Run Code Online (Sandbox Code Playgroud)

但这不起作用,我收到此错误:

file = models.FileField(upload_to=UploadItem.get_directory) 
NameError: name 'UploadItem' is not defined
Run Code Online (Sandbox Code Playgroud)

Dam*_*nic 6

如果您需要使用基类属性作为子类的一部分,可以通过类似的方式进行一些调整来完成:

import os

# ...

def get_directory(instance, filename):
    return instance.get_file_directory(filename)


class UploadItem(models.Model):
    FILE_DIRECTORY = 'files/'

    file = models.FileField(upload_to=get_directory) 

    class Meta:
        abstract = True

    @staticmethod
    def get_file_directory(filename):
        return os.path.join(UploadItem.FILE_DIRECTORY, filename)
Run Code Online (Sandbox Code Playgroud)

然后在子类中:

class Video(UploadItem):
    FILE_DIRECTORY = 'videos/'

    def get_file_directory(self, filename):
        filename = os.path.join(self.FILE_DIRECTORY, filename)
        return super().get_document_path(filename)
Run Code Online (Sandbox Code Playgroud)

这样你就会得到upload_to等于:

  • files为了UploadItem
  • files/videos为了Video

对于需要共享一些公共基本属性的更复杂的对象可能有用。


Man*_*dan 5

鉴于评估时错误是自然的

file = models.FileField(upload_to=UploadItem.get_directory) 
Run Code Online (Sandbox Code Playgroud)

UploadItem类尚未确定.您可以执行以下操作以使其工作:

def get_directory():
    pass

class UploadItem(models.Model):
    file = models.FileField(upload_to=get_directory)

    class Meta:
        abstract = True
Run Code Online (Sandbox Code Playgroud)

但这并不能解决你所有的问题.get_directoryVideo类中添加(或覆盖)方法不会更改模型upload_to属性的file属性.

更新

文件说,upload_to可能是一个可调用.

这也可以是可调用的,例如函数,它将被调用以获得上载路径,包括文件名.这个callable必须能够接受两个参数,并返回一个Unix风格的路径(带有正斜杠)以传递给存储系统.

鉴于此,我们可以编写一个自定义回调函数,如下所示:

categories_and_paths = { 'video': 'videos/', 'photo': 'photos/' } # etc.
def get_directory(instance, filename):
    category = instance.category
    return categories_and_paths.get(category, '')
Run Code Online (Sandbox Code Playgroud)

Instance这里将是相应模型的实例.为此,每个模型实例都应该有一个类别字段.我们可以在模型的主体中添加一个.

class Video(UploadItem):
    category = 'video'
Run Code Online (Sandbox Code Playgroud)