我如何获得ForeignKey的pk?

时间:2014-06-24 23:21:25

标签: python django

我想允许以下列方式存储的上传内容:

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中组织文件上传的策略?

2 个答案:

答案 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实例中可用Uploadself.category_id相关的pkUser

更复杂的是,要使用动态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)