如何使用upload_to将文件保存到模型中以获取动态路径

时间:2017-07-27 17:01:34

标签: python django django-models django-file-upload

我正在尝试为每个用户创建一个文件夹来放置他们的项目。因此,他们的文件将包含路径..\project\id\filenameid是用户id和{{1}是文件的名称。现在使用filenameupload_toinstancefilename}允许的参数,我意识到Filefield将是instance.id和路径该文件将为None而不是..\project\None\filename

现在阅读Django documentation upload_to我看到了这个:

  

在大多数情况下,此对象不会保存到数据库中   但是,如果它使用默认的AutoField,它可能还没有   主键字段的值。

我的解释是创建新记录并且..\project\id\filename没有同时实例化,也就是说,当我在user_directory_path模型上调用create时,Project将是instance.id。我现在的问题是,有办法解决这个问题吗?虽然我看到None很方便,但对于我正在做的动态路径来说并不一定方便。我正在考虑创建记录,然后在更新中添加文件路径,但我正在寻找一种可以一步保存所有内容的方法。

upload_to

当表单通过验证时,这是models.py def user_directory_path(instance, filename): # file will be uploaded to MEDIA_ROOT/user_<id>/<filename> return 'project/{0}/{1}'.format(instance.user.id, filename) class Project(models.Model): email = models.ForeignKey(User, to_field="email", max_length=50 ) title = models.CharField(max_length=100) date_created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) file = models.FileField(upload_to=user_directory_path, validators=[validate_file_type], null=True) 。请注意views.py之前调用user_directory_path

create

2 个答案:

答案 0 :(得分:2)

如果如你所说,你想在文件路径中使用的id是用户的id,而不是Project的id ..那么没有问题因为用户已经存在正在保存项目。由于emailUser的外键,您只需执行以下操作:

def user_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    return 'project/{0}/{1}'.format(instance.email.id, filename)

但是我会指出,在Django的做事方式中,创建一个名为email的字段是User的外键实际上非常令人困惑。数据库中的字段将被称为email_id ..并且模型字段的值将返回User的实例..而不是实际的电子邮件地址,即使电子邮件地址是&#39;存储在列中。要获取电子邮件地址,您需要执行以下操作之一:

myproject.email.email    
myproject.email_id

两者都不是很清楚。因此,除非您有充分的理由这样做,否则应调用字段user并删除to_field='email'。允许Django通过id加入表,这是默认行为。

然后,如果您需要用户电子邮件地址,您可以随时通过

获取
 myproject.user.email  

奖金是,如果用户更改了他们的电子邮件地址,它将随处更改,您不必依赖级联更新来修复所有外键。

相信我,在使用Django时你想通过id(默认)做ForeignKey,除非有原因...

答案 1 :(得分:1)

一个简单的解决方案是保存没有文件的对象,然后像这样保存文件

email = request.user.email
title = request.POST.get('title', '')
file = request.FILES['file']
filename = file.name
instance = Usermie.objects.get(email=request.user.email)

# Save to model
user_directory_path(instance=instance, filename=filename)
project = Project.objects.create(title=title)
project.file = file
project.save()