django FileSystemStorage的动态路径

时间:2015-09-03 05:52:10

标签: python django django-models filefield

我试图使用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)

但是当我保存此模型的对象时,只有文件名存储在db。

因此,当我尝试访问路径时,它返回附加了今天日期的路径,而不是上传日期。 即。如果我上传一个文件,比如说09-21-2015,我试着在第二天访问该路径,它将返回 account/files/09-22-2015/<file_name>这将是一条无效的路径。 那么应该做什么调整来存储db中的绝对路径。或者我在这里做错了什么?

2 个答案:

答案 0 :(得分:3)

我很确定,你的版本没有按照你的意图行事:

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')

至于解释:

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

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

  1. 检索请求路径,这是文件上传的路径。
  2. 检查是否为文件字段指定了upload_to选项。 如果upload_to是字符串,请将此字符串用作基目录。 upload_to运行strftime()以处理任何日期说明符。连接upload_to和请求路径,这将导致相对于存储的目标路径。
  3. 如果upload_to是可调用的,请使用(instance, request_path)调用它,并使用返回值作为目标路径(相对于存储)。
  4. 检查文件是否已存在于存储中。如果是这样,请获得一条新的,独特的路径。
  5. 使用目标路径将文件保存到存储。
  6. 将目标路径(仍然相对于存储)存储在数据库中。
  7. 正如人们所看到的,存储意味着或多或少是静态的。更改存储可能会使数据库中的所有现有文件路径无效,因为它们与存储相关。

答案 1 :(得分:0)

解决了同样的问题。它将文件从本地机器上传到服务器
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>"})