我想允许以下列方式存储的上传内容:
class Upload(models.Model):
user = models.ForeignKey(User)
category = models.ForeignKey(Category)
file = models.FileField(upload_to='uploads/' + str(category.pk) + '/' + str(user.pk))
class Meta:
unique_together = ('user', 'category')
这样,每个上传都将在其自己的目录中进行沙盒化,首先是类别ID,然后是用户ID。我不必担心重复的文件名,目录结构整洁有序。
但是,ForeignKey
没有pk
的实例,因此上述代码实际上不起作用。有没有办法根据类别和用户将文件存储在目录中?或者,是否有另一种常用于在Django中组织文件上传的策略?
答案 0 :(得分:0)
您可以使用upload_to的可调用函数:
import os
def upload_path(instance, filename):
return os.path.join('uploads', str(instance.category.pk), str(instance.user.pk))
file = models.FileField(upload_to=upload_path)
答案 1 :(得分:0)
这里要解决两件事。
快速的是,相关pk
的{{1}}在内存Category
实例中可用Upload
和self.category_id
相关的pk
是User
。
更复杂的是,要使用动态self.user_id
,您必须为其提供可调用而非任意表达式。来自the docs:
这也可以是一个可调用的函数,例如一个函数,它将被调用以获取上传路径,包括文件名。这个callable必须能够接受两个参数,并返回一个Unix风格的路径(带有正斜杠)以传递给存储系统。将传递的两个参数是:
实例
定义FileField的模型实例。更具体地说,这是附加当前文件的特定实例。
在大多数情况下,此对象尚未保存到数据库中,因此如果它使用默认的AutoField,则可能还没有其主键字段的值。
文件名
最初提供给文件的文件名。在确定最终目的地路径时,可能会或可能不会考虑这一点。
因此,您需要定义一个带有upload_to
实例并返回所需路径的函数:
Upload
或类似的东西。然后在模型中使用它:
def upload_location(upload, original_filename):
return os.path.join(str(upload.category_id), str(upload.user_id), original_filename)