将一个回调作为upload_to传递给FileField [英] passing a callback as upload_to to FileField

查看:106
本文介绍了将一个回调作为upload_to传递给FileField的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这是一个例子:

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


class Meta:
abstract = True
#我想让视频存储在'videos /'目录中
class视频(UploadItem):
def get_directory(self,instance,filename):
return'视频/'

但是这不行,我得到这个错误:

  file = models.FileField(upload_to = UploadItem.get_directory)
NameError:name'UploadItem'未定义


解决方案

错误是自然的,因为在评估

$ b时
$ b

  file = models.FileField(upload_to = UploadItem.get_directory)

尚未定义 UploadItem 类。您可以执行以下操作使其正常工作:

  def get_directory():
pass

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

class Meta:
abstract = True

这不会解决你所有的问题。在视频类中添加(或覆盖)方法 get_directory 不会更改 upload_to 属性的文件属性。



更新



文档说, upload_to 可以是可调用的。


这也可以是一个可调用的函数,例如函数,将被调用来获取上传路径,包括文件名。此可调用必须能够接受两个参数,并返回一个Unix样式的路径(带有斜杠),以传递到存储系统。


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

  categories_and_paths = {'video':'videos /','photo':'照片/'}#等
def get_directory(instance,filename):
category = instance.category
return categories_and_paths.get(category,'')

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

  class Video(UploadItem):
category ='video'


I have an abstract model class UploadItem for handling uploaded files. I want each subclass to be able to define the upload_to path. For this, i pass a callback to the constructor of FileField.

This is an example:

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/'

But this doesn't work, i am getting this error:

file = models.FileField(upload_to=UploadItem.get_directory) 
NameError: name 'UploadItem' is not defined

解决方案

The error is natural given that at the time of evaluating

file = models.FileField(upload_to=UploadItem.get_directory) 

the UploadItem class is not yet defined. You can do the following to make it work:

def get_directory():
    pass

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

    class Meta:
        abstract = True

This won't solve all your problems though. Adding (or overriding) a method get_directory in the Video class will not change the upload_to property of the file attribute of the model.

Update

The documentation says that the upload_to can be a callable.

This may also be a callable, such as a function, which will be called to obtain the upload path, including the filename. This callable must be able to accept two arguments, and return a Unix-style path (with forward slashes) to be passed along to the storage system.

Given this we can write a custom call back function like this:

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

Instance here will be the instance of the respective model. For this to work each model instance should have a category field. We can add one in the body of the model.

class Video(UploadItem):
    category = 'video'

这篇关于将一个回调作为upload_to传递给FileField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆