Django FileField,在运行时确定upload_to

Tee*_*bes 127 python django django-models

我正在尝试设置我的上传,以便如果用户joe上传文件,则转到MEDIA_ROOT/joe,而不是让每个人的文件都转到MEDIA_ROOT.问题是我不知道如何在模型中定义它.以下是目前的情况:

class Content(models.Model):
    name = models.CharField(max_length=200)
    user = models.ForeignKey(User)
    file = models.FileField(upload_to='.')
Run Code Online (Sandbox Code Playgroud)

所以我想要的不是'.' 作为upload_to,让它成为用户的名字.

据我所知,从Django 1.0开始,您可以定义自己的函数来处理upload_to,但该函数不知道用户是谁,所以我有点迷失.

谢谢您的帮助!

Smi*_*ris 250

你可能已经阅读过这些文档了,所以这里有一个简单的例子让它变得有意义:

def content_file_name(instance, filename):
    return '/'.join(['content', instance.user.username, filename])

class Content(models.Model):
    name = models.CharField(max_length=200)
    user = models.ForeignKey(User)
    file = models.FileField(upload_to=content_file_name)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,您甚至不需要使用给定的文件名 - 如果您愿意,您也可以在upload_to中调用它.

  • 您可能希望使用`os.path.join`而不是`'/'.join`来确保它也适用于非Unix系统.它们可能很少见,但这是很好的做法;) (11认同)
  • 奇怪的是,这基本上在同样的设置中失败了.instance.user没有属性. (3认同)
  • 这适用于ModelForm吗?我可以看到该实例具有类模型的所有属性,但没有值(只是字段名称的str).在模板中,用户被隐藏.我可能要提交一个问题,我一直在谷歌上搜索几个小时. (2认同)
  • 嗨,我尝试了相同的代码,将它们放在models.py中,但得到错误内容对象没有属性'user'. (2认同)

gda*_*ram 12

这确实有帮助.为了更简洁一点,我决定在我的情况下使用lambda:

file = models.FileField(
    upload_to=lambda instance, filename: '/'.join(['mymodel', str(instance.pk), filename]),
)
Run Code Online (Sandbox Code Playgroud)

  • lambda 不适用于“迁移”操作,因为它无法根据[文档](https://docs.djangoproject.com/en/2.1/ref/models/fields/#s-default)进行序列化 (3认同)
  • 这在使用迁移的Django 1.7中对我不起作用.结束创建一个函数并进行迁移. (2认同)
  • 实例在保存之前没有`pk`。它仅适用于更新,不适用于创建(插入)。 (2认同)

小智 5

关于使用“实例”对象的 pk 值的说明。根据文档:

在大多数情况下,这个对象还没有被保存到数据库中,所以如果它使用默认的 AutoField,它的主键字段可能还没有值。

因此,使用 pk 的有效性取决于您的特定模型是如何定义的。