django FileSystemStorage 的动态路径

Dynamic path for django FileSystemStorage

我试图使用 Django FileSystemStorage 保存一些文件。我的模型如下图

key_store = FileSystemStorage(
location='account/files/'+datetime.date.today().isoformat())


class Account(models.Model):
    name = models.CharField(max_length=100, null=True, blank=True)
    user = models.ForeignKey(User, related_name='auth_user_account_relation')
    subscription_id = models.CharField(max_length=100, null=True, blank=True)
    info_file = models.FileField(storage=key_store)

但是当我保存这个模型的对象时,只有文件名存储在数据库中。

因此,当我尝试访问路径时,它 returns 路径附加了今天的日期,而不是上传日期。 IE。如果我在 2015 年 9 月 21 日上传文件并在第二天尝试访问该路径,它将 return account/files/09-22-2015/<file_name> 这将是一个无效的路径。 那么应该进行哪些调整以将绝对路径存储在数据库中。或者我在这里做错了什么?

我很确定,您的版本没有按照您的预期运行:

key_store = FileSystemStorage(
    location='account/files/'+datetime.date.today().isoformat()
)

在加载模块时进行评估(通常仅在您启动应用程序时)。之后,只要不重新加载模块,日期就会保持不变。因此它指向一个包含应用程序启动日期名称的目录,这可能不是您想要的。

此外,FileSystemStorage 使用完整路径名进行序列化,这意味着这也会每隔一天触发一次迁移(因为存储路径已更改)。

您可以通过结合使用 FileSystemStorage(将文件存储在媒体目录之外)和 upload_to 以及可调用的方法来解决此问题:

key_store = FileSystemStorage(location='account/files/')

def key_store_upload_to(instance, path):
    # prepend date to path
    return os.path.join(
        datetime.date.today().isoformat(), 
        path
    )

class Account(models.Model):
    # [...]
    info_file = models.FileField(storage=key_store, upload_to=key_store_upload_to)

这使用新的 FileSystemStorage 作为上传文件的基本目录,并使用 upload_to 确定上传文件相对于存储根目录的名称。

编辑 1:感谢您指出 upload_to 采用日期格式。

由于 upload_to 也采用 strftime() 格式说明符,因此也可以在没有可调用对象的情况下实现与纯日期相关的路径选择:

info_file = models.FileField(storage=key_store, upload_to='account/files/%Y-%m-%d')

至于说明:

A storage本质上是django中分层文件系统的抽象。 FileFields 总是将他们的文件存储在 storage 中。默认情况下使用 媒体存储 ,但可以更改。

要确定文件上传到的路径,FileField 大致执行以下操作

  1. 检索请求路径,这是上传文件的路径。
  2. 检查是否为文件字段指定了 upload_to 选项。 如果 upload_to 是一个字符串,则使用该字符串作为基本目录。 upload_to 是 运行 到 strftime() 以处理任何日期说明符。连接 upload_to 和请求路径,这导致相对于存储的目标路径。
  3. 如果upload_to是可调用的,用(instance, request_path)调用它并使用return值作为目标路径(相对于存储)。
  4. 检查存储中是否已存在该文件。如果是这样,导出一条新的、唯一的路径。
  5. 将文件保存到目标路径的存储中。
  6. 将目标路径(仍然相对于存储)存储在数据库中。

如您所见,存储或多或少应该是静态的。更改存储可能会使数据库中的所有现有文件路径无效,因为它们是相对于存储的。

解决了同样的问题。它将文件从本地机器上传到服务器
views.py

def receiveAudioRecord(request):

    if not os.path.exists('recording/wavFiles'):
        os.makedirs('recording/wavFiles')

    if not request.FILES['fileupload']:
        return render(request, "recording.html", {'msg': "Try Again! Unable to upload. </span>"})

    elif request.method == 'POST' and request.FILES['fileupload']:
        myfile = request.FILES['fileupload']
        fs = FileSystemStorage("recording/wavFiles")
        filename = fs.save(myfile.name, myfile)  # saves the file to `media` folder
        fs.url(filename)  # gets the url

        return render(request, "recording.html",{'msg':"successfully uploaded"})
    else:
        return render(request,"recording.html",{'msg':"Try Again! Unable to upload. </span>"})